#! /usr/bin/env python3
'''
Copyright (C) 2012-2021  Diego Torres Milano
Created on Feb 3, 2012

@author: diego
'''

from __future__ import print_function

__version__ = '21.12.0'

import getopt
import os
import sys

try:
    sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
except:
    pass

from com.dtmilano.android.viewclient import ViewClient, View, ViewClientOptions
from com.dtmilano.android.common import debugArgsToDict

HELP = 'help'
VERBOSE = 'verbose'
VERSION = 'version'
DEBUG = 'debug'
IGNORE_SECURE_DEVICE = 'ignore-secure-device'
IGNORE_VERSION_CHECK = 'ignore-version-check'
FORCE_VIEW_SERVER_USE = 'force-view-server-use'
DO_NOT_START_VIEW_SERVER = 'do-not-start-view-server'
DO_NOT_IGNORE_UIAUTOMATOR_KILLED = 'do-not-ignore-uiautomator-killed'
WINDOW = 'window'
ALL = 'all'
UNIQUE_ID = 'uniqueId'
POSITION = 'position'
BOUNDS = 'bounds'
CONTENT_DESCRIPTION = 'content-description'
TAG = 'tag'
CENTER = 'center'
SAVE_SCREENSHOT = 'save-screenshot'
SAVE_VIEW_SCREENSHOTS = 'save-view-screenshots'
DO_NOT_DUMP_VIEWS = 'do-not-dump-views'
DEVICE_ART = 'device-art'
DROP_SHADOW = 'drop-shadow'
SCREEN_GLARE = 'glare'
USE_UIAUTOMATOR_HELPER = 'use-uiautomator-helper'

MAP = {
    'a': View.__str__, ALL: View.__str__,
    'i': ViewClient.TRAVERSE_CITUI, UNIQUE_ID: ViewClient.TRAVERSE_CITUI,
    'x': ViewClient.TRAVERSE_CITPS, POSITION: ViewClient.TRAVERSE_CITPS,
    'b': ViewClient.TRAVERSE_CITB, BOUNDS: ViewClient.TRAVERSE_CITB,
    'd': ViewClient.TRAVERSE_CITCD, CONTENT_DESCRIPTION: ViewClient.TRAVERSE_CITCD,
    'g': ViewClient.TRAVERSE_CITG, TAG: ViewClient.TRAVERSE_CITG,
    'c': ViewClient.TRAVERSE_CITC, CENTER: ViewClient.TRAVERSE_CITC,
    'W': ViewClient.TRAVERSE_CITCDS, SAVE_VIEW_SCREENSHOTS: ViewClient.TRAVERSE_CITCDS,
    'D': ViewClient.TRAVERSE_S, DO_NOT_DUMP_VIEWS: ViewClient.TRAVERSE_S
}

USAGE = 'usage: %s [OPTION]... [serialno]'
SHORT_OPTS = 'HVvIEFSkw:aixbdgcf:W:DA:ZBhX:'
LONG_OPTS = [HELP, VERBOSE, VERSION, IGNORE_SECURE_DEVICE, IGNORE_VERSION_CHECK, FORCE_VIEW_SERVER_USE,
             DO_NOT_START_VIEW_SERVER, DO_NOT_IGNORE_UIAUTOMATOR_KILLED, WINDOW + '=',
             ALL, UNIQUE_ID, POSITION, BOUNDS, CONTENT_DESCRIPTION, TAG, CENTER,
             SAVE_SCREENSHOT + '=', SAVE_VIEW_SCREENSHOTS + '=',
             DO_NOT_DUMP_VIEWS,
             DEVICE_ART + '=', DROP_SHADOW, SCREEN_GLARE,
             USE_UIAUTOMATOR_HELPER,
             DEBUG + '='
             ]
LONG_OPTS_ARG = {WINDOW: 'WINDOW', SAVE_SCREENSHOT: 'FILE', SAVE_VIEW_SCREENSHOTS: 'DIR', DEVICE_ART: 'MODEL',
                 DEBUG: 'LIST'}
OPTS_HELP = {
    'H': 'prints this help',
    'V': 'verbose comments',
    'I': 'ignore secure device',
    'F': 'force view server use (even if UiAutomator present)',
    'S': 'don\'t start ViewServer',
    'k': 'don\'t ignore UiAutomator killed',
    'w': 'dump WINDOW content (default: -1, all windows)',
    'a': 'dump all information about Views',
    'i': 'dump View unique IDs',
    'x': 'dump View positions',
    'b': 'dump View bounds',
    'd': 'dump View content descriptions',
    'g': 'dump View tags',
    'c': 'dump View centers',
    'f': 'save screenshot to file',
    'W': 'save View screenshots to files in directory',
    'E': 'ignores ADB version check',
    'D': 'don\'t dump views, only useful if you specified -f or -W',
    'A': 'device art model to frame screenshot (auto: autodetected)',
    'Z': 'drop shadow for device art screenshot',
    'B': 'screen glare over screenshot',
    'h': 'use UiAutomatorHelper Android app',
    'X': 'debug options',
}


def shortAndLongOptions():
    '''
    @return: the list of corresponding (short-option, long-option) tuples
    '''

    short_opts = SHORT_OPTS.replace(':', '')
    if len(short_opts) != len(LONG_OPTS):
        raise Exception('There is a mismatch between short and long options')
    t = tuple(short_opts) + tuple(LONG_OPTS)
    l2 = int(len(t) / 2)
    sl = []
    for i in range(l2):
        sl.append((t[i], t[i + l2]))
    return sl


def usage(exitVal=1):
    print(USAGE % progname, file=sys.stderr)
    print("Try '%s --help' for more information." % progname, file=sys.stderr)
    sys.exit(exitVal)


def _help():
    print(USAGE % progname, file=sys.stderr)
    print(file=sys.stderr)
    print("Options:", file=sys.stderr)
    for so, lo in shortAndLongOptions():
        o = '  -%c, --%s' % (so, lo)
        if lo[-1] == '=':
            o += LONG_OPTS_ARG[lo[:-1]]
        try:
            o = '%-34s %-45s' % (o, OPTS_HELP[so])
        except:
            pass
        print(o, file=sys.stderr)
    sys.exit(0)


def version():
    print('{} version {}'.format(progname, __version__))
    sys.exit(0)


# __main__
progname = os.path.basename(sys.argv[0])
try:
    opts, args = getopt.getopt(sys.argv[1:], SHORT_OPTS, LONG_OPTS)
    sys.argv[1:] = args
except getopt.GetoptError as e:
    print('ERROR:', str(e), file=sys.stderr)
    usage()

kwargs1 = {VERBOSE: False, 'ignoresecuredevice': False, 'ignoreversioncheck': False}
kwargs2 = {ViewClientOptions.FORCE_VIEW_SERVER_USE: False, ViewClientOptions.START_VIEW_SERVER: True,
           ViewClientOptions.AUTO_DUMP: False, ViewClientOptions.IGNORE_UIAUTOMATOR_KILLED: True,
           ViewClientOptions.COMPRESSED_DUMP: True,
           ViewClientOptions.USE_UIAUTOMATOR_HELPER: False,
           ViewClientOptions.DEBUG: {},
           }
options = {WINDOW: -1, SAVE_SCREENSHOT: None, SAVE_VIEW_SCREENSHOTS: None, DO_NOT_DUMP_VIEWS: False,
           DEVICE_ART: None, DROP_SHADOW: False, SCREEN_GLARE: False}
transform = ViewClient.TRAVERSE_CIT
for o, a in opts:
    o = o.strip('-')
    if o in ['H', HELP]:
        _help()
    elif o in ['V', VERBOSE]:
        kwargs1[VERBOSE] = True
    elif o in ['v', VERSION]:
        version()
    elif o in ['I', IGNORE_SECURE_DEVICE]:
        kwargs1['ignoresecuredevice'] = True
    elif o in ['E', IGNORE_VERSION_CHECK]:
        kwargs1['ignoreversioncheck'] = True
    elif o in ['F', FORCE_VIEW_SERVER_USE]:
        kwargs2[ViewClientOptions.FORCE_VIEW_SERVER_USE] = True
    elif o in ['S', DO_NOT_START_VIEW_SERVER]:
        kwargs2[ViewClientOptions.START_VIEW_SERVER] = False
    elif o in ['k', DO_NOT_IGNORE_UIAUTOMATOR_KILLED]:
        kwargs2[ViewClientOptions.IGNORE_UIAUTOMATOR_KILLED] = False
    elif o in ['w', WINDOW]:
        options[WINDOW] = a
    elif o in ['f', SAVE_SCREENSHOT]:
        options[SAVE_SCREENSHOT] = a
    elif o in ['W', SAVE_VIEW_SCREENSHOTS]:
        options[SAVE_VIEW_SCREENSHOTS] = a
        transform = MAP[o]
    elif o in ['A', DEVICE_ART]:
        options[DEVICE_ART] = a
    elif o in ['Z', DROP_SHADOW]:
        options[DROP_SHADOW] = True
    elif o in ['B', SCREEN_GLARE]:
        options[SCREEN_GLARE] = True
    elif o in ['h', USE_UIAUTOMATOR_HELPER]:
        kwargs2[ViewClientOptions.USE_UIAUTOMATOR_HELPER] = True
    elif o in ['D', DO_NOT_DUMP_VIEWS]:
        options[DO_NOT_DUMP_VIEWS] = True
        transform = MAP[o]
    elif o in ['X', DEBUG]:
        kwargs2[ViewClientOptions.DEBUG] = debugArgsToDict(a)
    else:
        transform = MAP[o]

if options[DO_NOT_DUMP_VIEWS]:
    transform = MAP[DO_NOT_DUMP_VIEWS]

vc = ViewClient(*ViewClient.connectToDeviceOrExit(**kwargs1), **kwargs2)
if options[WINDOW] == 'list':
    vc.list()
    sys.exit(0)
if options[SAVE_SCREENSHOT]:
    vc.device.reconnect = True  # (not options[DO_NOT_DUMP_VIEWS])
    ext = os.path.splitext(options[SAVE_SCREENSHOT])[1][1:].upper()
    _format = ext
    if ext == 'JPG':
        _format = 'JPEG'
    vc.writeImageToFile(options[SAVE_SCREENSHOT], _format=_format, deviceart=options[DEVICE_ART],
                        dropshadow=options[DROP_SHADOW], screenglare=options[SCREEN_GLARE])
if not options[DO_NOT_DUMP_VIEWS] or options[SAVE_VIEW_SCREENSHOTS]:
    vc.dump(window=options[WINDOW])
    ViewClient.imageDirectory = options[SAVE_VIEW_SCREENSHOTS]
    vc.traverse(transform=transform)
if kwargs2[ViewClientOptions.USE_UIAUTOMATOR_HELPER]:
    try:
        vc.uiAutomatorHelper.quit()
    except:
        pass
