#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
Copyright (C) 2013-2014  Diego Torres Milano
Created on Mar 28, 2013

Culebra helps you create AndroidViewClient scripts generating a working template that can be
modified to suit more specific needs.
                      __    __    __    __
                     /  \  /  \  /  \  /  \ 
____________________/  __\/  __\/  __\/  __\_____________________________
___________________/  /__/  /__/  /__/  /________________________________
                   | / \   / \   / \   / \   \___
                   |/   \_/   \_/   \_/   \    o \ 
                                           \_____/--<

@author: Diego Torres Milano
@author: Jennifer E. Swofford (ascii art snake)

'''

__version__ = '8.3.3'

import re
import sys
import os
import getopt
import warnings
import subprocess
import codecs
import calendar
from datetime import date

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, CulebraOptions
from com.dtmilano.android.culebron import Culebron, Operation

DEBUG = False
USAGE = 'usage: %s [OPTION]... [serialno]'

class Descriptor:
    CONTENT_DESCRIPTION = 'content-description'
    TEXT = 'text'
    ID = 'id'

    @staticmethod
    def findBestDescriptor(view):
        '''
        Finds the best possible descriptor for the View
        '''
        
        cd = view.getContentDescription()
        if cd and options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]:
            return Descriptor.CONTENT_DESCRIPTION
        else:
            t = view.getText()
            if t and options[CulebraOptions.FIND_VIEWS_WITH_TEXT]:
                return Descriptor.TEXT
        return Descriptor.ID
    

def fillAutoRegexpsRes():
    are = {}
    are['clock'] = re.compile('[012]?\d:[0-5]\d')
    d = "("
    for i in range(7):
        d += calendar.day_abbr[i]
        if i != 6:
            d += '|'
    d += '), ('
    for i in range(1, 13):
        d += calendar.month_name[i]
        if i != 12:
            d += '|'
    d += ') [0123]\d'
    are['date'] = re.compile(d, re.IGNORECASE)
    are['battery'] = re.compile('Charging, \d\d%')
    return are

CulebraOptions.AUTO_REGEXPS_RES = fillAutoRegexpsRes()
SB_NO_JAR = 'no-jar'
SB_JAR = 'jar'
SB_JAR_LINUX = 'jar-linux'
SHEBANG = {
    SB_NO_JAR: '#! /usr/bin/env python',
    SB_JAR: '#! /usr/bin/env shebang monkeyrunner -plugin $ANDROID_VIEW_CLIENT_HOME/bin/androidviewclient-$ANDROID_VIEW_CLIENT_VERSION.jar @!',
    SB_JAR_LINUX: '#! /usr/local/bin/shebang monkeyrunner -plugin $AVC_HOME/bin/androidviewclient-$AVC_VERSION.jar @!'
    }

indent = ''
prefix = ''

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

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

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

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

def version():
    print progname, __version__
    sys.exit(0)

def autoRegexpsHelp():
    print >> sys.stderr, "Available %s options:" % CulebraOptions.AUTO_REGEXPS
    print >> sys.stderr, "\thelp: prints this help"
    print >> sys.stderr, "\tall: includes all the available regexps"
    for r in CulebraOptions.AUTO_REGEXPS_RES:
        print >> sys.stderr, "\t%s: %s" % (r, CulebraOptions.AUTO_REGEXPS_RES[r].pattern)
    print >> sys.stderr
    sys.exit(0)

def error(msg, fatal=False):
    print >> sys.stderr, "%s: ERROR: %s" % (progname, msg)
    if fatal:
        sys.exit(1)

def notNull(val, default):
    if val:
        return val
    return default

def printVerboseComments(view):
    '''
    Prints the verbose comments for view.
    '''

    print '\n%s# class=%s' % (indent, view.getClass()),
    try:
        text = view.getText()
        if text:
            u = 'u' if isinstance(text, unicode) else ''
            if '\n' in text:
                text = re.sub(r'\n(.)', r'\n#\1', text)
            print "text=%c'%s'" % (u, text),
    except:
        pass
    try:
        tag = view.getTag()
        if tag != 'null':
            print 'tag=%s' % tag,
    except:
        pass
    print

def variableNameFromIdOrKey(view):
    '''
    Returns a suitable variable name from the id.

    @type view: L{View}
    @param id: the View from where the I{uniqueId} is obtained

    @return: the variable name from the id
    '''

    var = view.variableNameFromId()
    if options[CulebraOptions.USE_DICTIONARY]:
        return '%sviews[\'%s\']' % (prefix, notNull(dictionaryKeyFrom(options[CulebraOptions.DICTIONARY_KEYS_FROM], view), var))
    else:
        return var

def dictionaryKeyFrom(key, view):
    if key == 'id':
        return view.getUniqueId()
    elif key == 'text':
        return view.getText()
    elif key == 'content-description':
        return view.getContentDescription()
    else:
        raise Exception('Not a valid dictionary key: %s' % key)

def escapeRegexpSpecialChars(text):
    return re.escape(text)

def printFindViewWithText(view, useregexp, op=Operation.ASSIGN, arg=None):
    '''
    Prints the corresponding statement.

    @type view: L{View}
    @param view: the View
    '''

    text = view.getText()
    isUnicode = isinstance(text, unicode)
    if isUnicode and sys.stdout.encoding is None:
        warnings.warn('''\
You are trying to print unicode characters to an unencoded stdout, it will probably fail.
You have to set PYTHONIOENCODING environment variable. For example:
       export PYTHONIOENCODING=utf-8
        ''')

    u = 'u' if isUnicode else ''
    if text:
        var = variableNameFromIdOrKey(view)
        # if there are special chars already in the text scape them
        text = escapeRegexpSpecialChars(text)
        if text.find(u"\n") > 0 or text.find(u"'") > 0:
            # 2 quotes + 1 quote = 3 quotes
            text = "''%s''" % text
        if useregexp:
            if options[CulebraOptions.AUTO_REGEXPS]:
                for r in options[CulebraOptions.AUTO_REGEXPS]:
                    autoRegexp = CulebraOptions.AUTO_REGEXPS_RES[r]
                    if autoRegexp.match(text):
                        text = autoRegexp.pattern
                        break
            text = "re.compile(%s'%s')" % (u, text)
        else:
            text = "%s'%s'" % (u, text)
            
        if op == Operation.ASSIGN:
            print u'%s%s = %svc.findViewWithTextOrRaise(%s)' % (indent, var, prefix, text)
        elif op == Operation.TOUCH:
            print u'%s%svc.findViewWithTextOrRaise(%s).touch()' % (indent, prefix, text)
        elif op == Operation.TYPE:
            print '%s%svc.findViewWithTextOrRaise("%s").type(u"%s")' % (indent, prefix, text, arg)
        elif op == Operation.TEST:
            print '%s%sassertIsNotNone(%svc.findViewWithText(%s))' % (indent, prefix, prefix, text)
    elif kwargs1[CulebraOptions.VERBOSE]:
        warnings.warn('View with id=%s has no text' % view.getUniqueId())

def printFindViewWithContentDescription(view, useregexp, op=Operation.ASSIGN, arg=None):
    '''
    Prints the corresponding statement.

    @type view: L{View}
    @param view: the View
    '''

    contentDescription = view.getContentDescription()
    if contentDescription:
        var = variableNameFromIdOrKey(view)
        if useregexp:
            if options[CulebraOptions.AUTO_REGEXPS]:
                for r in options[CulebraOptions.AUTO_REGEXPS]:
                    autoRegexp = CulebraOptions.AUTO_REGEXPS_RES[r]
                    if autoRegexp.match(contentDescription):
                        contentDescription = autoRegexp.pattern
                        break
            contentDescription = "re.compile(u'''%s''')" % contentDescription
        else:
            contentDescription = "u'''%s'''" % contentDescription
        
        if op == Operation.ASSIGN:
            print '%s%s = %svc.findViewWithContentDescriptionOrRaise(%s)' % (indent, var, prefix, contentDescription)
        elif op == Operation.TOUCH:
            print '%s%svc.findViewWithContentDescriptionOrRaise(%s).touch()' % (indent, prefix, contentDescription)
        elif op == Operation.TYPE:
            print '%s%svc.findViewWithContentDescriptionOrRaise(%s).type(u"%s")' % (indent, prefix, contentDescription, arg)
        elif op == Operation.TEST:
            print '%s%sassertEquals(%svc.findViewWithContentDescriptionOrRaise(%s).getText(), u'''%s''')' % (indent, prefix, prefix, contentDescription, arg)
        else:
            error("Invalid operation: %s" % op)
            
    elif kwargs1[CulebraOptions.VERBOSE]:
        warnings.warn('View with id=%s has no content-description' % view.getUniqueId())

def printFindViewById(view, op=Operation.ASSIGN, arg=None):
    '''
    Prints the corresponding statement.

    @type view: L{View}
    @param view: the View
    '''

    var = variableNameFromIdOrKey(view)
    _id = view.getId() if view.getId() else view.getUniqueId()
    if op == Operation.ASSIGN:
        print '%s%s = %svc.findViewByIdOrRaise("%s")' % (indent, var, prefix, _id)
    elif op == Operation.TOUCH:
        print '%s%svc.findViewByIdOrRaise("%s").touch()' % (indent, prefix, _id)
    elif op == Operation.TYPE:
        print '%s%svc.findViewByIdOrRaise("%s").type(u"%s")' % (indent, prefix, _id, arg)
    elif op == Operation.TEST:
        print '%s%sassertEquals(%svc.findViewByIdOrRaise("%s").getText(), u'''%s''')' % (indent, prefix, prefix, _id, arg)
    else:
        error("Invalid operation: %s" % op)

def printDump(window):
    '''
    Prints a dump
    '''
    
    print '%s%svc.dump(window=%d)' % (indent, prefix, window)
    
def printSleep(secs):
    '''
    Prints a sleep
    '''
    
    print '%s%svc.sleep(%d)' % (indent, prefix, secs)
    
def printPress(keycode):
    '''
    Prints a key press
    '''
    
    print '%s%svc.device.press("%s")' % (indent, prefix, keycode)
    
def printDrag(start, end, duration, steps):
    '''
    Prints a drag
    '''
    
    print '%s%svc.device.drag(%s, %s, %d, %d)' % (indent, prefix, start, end, duration, steps) 
    
def printSaveViewScreenshot(view, dir):
    '''
    Prints the writeImageToFile.
    
    @type view: L{View}
    @param view: the View
    @type dir: str
    @param dir: the directory to store the images
    '''

    var = variableNameFromIdOrKey(view)
    print '%s%s.writeImageToFile(\'%s/%s.png\')' % (indent, var, dir, var)
    
def traverseAndPrint(view):
    '''
    Traverses the View tree and prints the corresponding statement.

    @type view: L{View}
    @param view: the View
    '''

    if options[CulebraOptions.VERBOSE_COMMENTS]:
        printVerboseComments(view)
    if options[CulebraOptions.FIND_VIEWS_BY_ID]:
        printFindViewById(view)
    if options[CulebraOptions.FIND_VIEWS_WITH_TEXT]:
        printFindViewWithText(view, options[CulebraOptions.USE_REGEXPS])
    if options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]:
        printFindViewWithContentDescription(view, options[CulebraOptions.USE_REGEXPS])
    if options[CulebraOptions.SAVE_VIEW_SCREENSHOTS]:
        printSaveViewScreenshot(view, options[CulebraOptions.SAVE_VIEW_SCREENSHOTS])

def printOperation(view, op, *args):
    if len(args) == 0:
        # We use tuple values in the rest of this method, so if an empty tuple was passed
        # replace it by one containing None
        args = ( None, )
    if DEBUG:
        print >> sys.stderr, "printOperation(",
        print >> sys.stderr, view.__str__(),
        print >> sys.stderr, ",", op, ",",
        for a in args:
            if isinstance(a, unicode):
                print >> sys.stderr, a.encode(encoding='ascii', errors='replace'), ", ", 
            else:
                print >> sys.stderr, a,
        print >> sys.stderr, ")"
    if op == Operation.SLEEP:
        printSleep(args[0])
        return
    elif op == Operation.PRESS:
        printPress(args[0])
        return
    elif op == Operation.DUMP:
        printDump(args[0])
        return
    elif op == Operation.DRAG:
        printDrag(args[0], args[1], args[2], args[3])
        return
    
    bd = Descriptor.findBestDescriptor(view)
    if bd == Descriptor.CONTENT_DESCRIPTION:
        printFindViewWithContentDescription(view, options[CulebraOptions.USE_REGEXPS], op, args[0])
    elif bd == Descriptor.TEXT:
        printFindViewWithText(view, options[CulebraOptions.USE_REGEXPS], op, args[0])
    else:
        printFindViewById(view, op, args[0])
        
def str2bool(v):
    return v.lower() in ("yes", "true", "t", "1", "on")

def value2dictionaryKey(v):
    v = v.lower()
    k = ['id', 'text', 'content-description']
    sk = ['i', 't', 'd']
    if v in k:
        return v
    if v in sk:
        return k[sk.index(v)]
    error("Invalid dictionary key: %s" % v)
    usage()

def getShebangJar():
    if options[CulebraOptions.USE_JAR]:
        import java
        osName = java.lang.System.getProperty('os.name')
        if osName == 'Linux':
            return SHEBANG[SB_JAR_LINUX]
        else:
            return SHEBANG[SB_JAR]
    else:
        return SHEBANG[SB_NO_JAR]

def getWindowOption():
    return options[CulebraOptions.WINDOW] if isinstance(options[CulebraOptions.WINDOW], str) and options[CulebraOptions.WINDOW][0] in '-0123456789' else "'%s'" % options[CulebraOptions.WINDOW]

def printScriptHeader():
    print '''%s
# -*- coding: utf-8 -*-
\'\'\'
Copyright (C) 2013-2014  Diego Torres Milano
Created on %s by Culebra v%s
                      __    __    __    __
                     /  \  /  \  /  \  /  \ 
____________________/  __\/  __\/  __\/  __\_____________________________
___________________/  /__/  /__/  /__/  /________________________________
                   | / \   / \   / \   / \   \___
                   |/   \_/   \_/   \_/   \    o \ 
                                           \_____/--<
@author: Diego Torres Milano
@author: Jennifer E. Swofford (ascii art snake)
\'\'\'


import re
import sys
import os
''' % (getShebangJar(), date.today(), __version__)

def printUnittestImport():
    print '''
import unittest
'''

def printAppendToSysPath():
    print '''
try:
    sys.path.append(os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
except:
    pass
'''

def runCulebron():
    Culebron.checkDependencies()
    culebron = Culebron(vc, printOperation, options[CulebraOptions.SCALE])
    culebron.takeScreenshotAndShowItOnWindow()
    culebron.mainloop()
    
################
# __main__
################
progname = os.path.basename(sys.argv[0])
try:
    optlist, args = getopt.getopt(sys.argv[1:], CulebraOptions.SHORT_OPTS, CulebraOptions.LONG_OPTS)
    sys.argv[1:] = args
except getopt.GetoptError, e:
    error(str(e))
    usage()

kwargs1 = {CulebraOptions.VERBOSE: False, 'ignoresecuredevice': False, 'ignoreversioncheck': False}
kwargs2 = {'forceviewserveruse': False, 'startviewserver': True, 'autodump': False, 'ignoreuiautomatorkilled': True}
options = {CulebraOptions.FIND_VIEWS_BY_ID: True, CulebraOptions.FIND_VIEWS_WITH_TEXT: False, CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION: False,
        CulebraOptions.USE_REGEXPS: False, CulebraOptions.VERBOSE_COMMENTS: False,
        CulebraOptions.UNIT_TEST_CLASS: False, CulebraOptions.UNIT_TEST_METHOD: None, CulebraOptions.USE_JAR: False,
        CulebraOptions.USE_DICTIONARY: False, CulebraOptions.DICTIONARY_KEYS_FROM: 'id',
        CulebraOptions.AUTO_REGEXPS: None, CulebraOptions.START_ACTIVITY: None, CulebraOptions.OUTPUT: None, CulebraOptions.INTERACTIVE: False,
        CulebraOptions.WINDOW:-1, CulebraOptions.APPEND_TO_SYS_PATH: False,
        CulebraOptions.SAVE_SCREENSHOT: None, CulebraOptions.SAVE_VIEW_SCREENSHOTS: None,
        CulebraOptions.GUI: False,
        CulebraOptions.DO_NOT_VERIFY_INITIAL_SCREEN_DUMP: False,
        CulebraOptions.SCALE: 1}
transform = traverseAndPrint
for o, a in optlist:
    o = o.strip('-')
    if o in ['H', CulebraOptions.HELP]:
        help()
    elif o in ['V', CulebraOptions.VERBOSE]:
        kwargs1[CulebraOptions.VERBOSE] = True
    elif o in ['v', CulebraOptions.VERSION]:
        version()
    elif o in ['I', CulebraOptions.IGNORE_SECURE_DEVICE]:
        kwargs1['ignoresecuredevice'] = True
    elif o in ['K', CulebraOptions.IGNORE_VERSION_CHECK]:
        kwargs1['ignoreversioncheck'] = True
    elif o in ['F', CulebraOptions.FORCE_VIEW_SERVER_USE]:
        kwargs2['forceviewserveruse'] = True
    elif o in ['S', CulebraOptions.DO_NOT_START_VIEW_SERVER]:
        kwargs2['startviewserver'] = False
    elif o in ['k', CulebraOptions.DO_NOT_IGNORE_UIAUTOMATOR_KILLED]:
        kwargs2['ignoreuiautomatorkilled'] = False
    elif o in ['w', CulebraOptions.WINDOW]:
         options[CulebraOptions.WINDOW] = a
    elif o in ['i', CulebraOptions.FIND_VIEWS_BY_ID]:
        options[CulebraOptions.FIND_VIEWS_BY_ID] = str2bool(a)
    elif o in ['t', CulebraOptions.FIND_VIEWS_WITH_TEXT]:
        options[CulebraOptions.FIND_VIEWS_WITH_TEXT] = str2bool(a)
    elif o in ['d', CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]:
        options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION] = str2bool(a)
    elif o in ['r', CulebraOptions.USE_REGEXPS]:
        options[CulebraOptions.USE_REGEXPS] = True
    elif o in ['C', CulebraOptions.VERBOSE_COMMENTS]:
        options[CulebraOptions.VERBOSE_COMMENTS] = True
    elif o in ['U', CulebraOptions.UNIT_TEST_CLASS]:
        # warnings.warn('Not implemented yet: %s' % o)
        options[CulebraOptions.UNIT_TEST_CLASS] = True
    elif o in ['M', CulebraOptions.UNIT_TEST_METHOD]:
        if not a.startswith('test'):
            warnings.warn('Method name should start with "test"')
    	options[CulebraOptions.UNIT_TEST_METHOD] = a
    elif o in ['j', CulebraOptions.USE_JAR]:
        options[CulebraOptions.USE_JAR] = str2bool(a)
    elif o in ['D', CulebraOptions.USE_DICTIONARY]:
        options[CulebraOptions.USE_DICTIONARY] = str2bool(a)
    elif o in ['K', CulebraOptions.DICTIONARY_KEYS_FROM]:
        options[CulebraOptions.DICTIONARY_KEYS_FROM] = value2dictionaryKey(a)
    elif o in ['R', CulebraOptions.AUTO_REGEXPS]:
        options[CulebraOptions.AUTO_REGEXPS] = a.split(',')
        for r in options[CulebraOptions.AUTO_REGEXPS]:
            if r == 'help':
                autoRegexpsHelp()
            if r == 'all':
                options[CulebraOptions.AUTO_REGEXPS] = CulebraOptions.AUTO_REGEXPS_RES.keys()
                break
            if r not in CulebraOptions.AUTO_REGEXPS_RES:
                error("invalid auto regexp: %s\n" % (r))
                usage()
        # CulebraOptions.AUTO_REGEPXS implies CulebraOptions.USE_REGEXPS
        options[CulebraOptions.USE_REGEXPS] = True
    elif o in ['a', CulebraOptions.START_ACTIVITY]:
        options[CulebraOptions.START_ACTIVITY] = a
    elif o in ['o', CulebraOptions.OUTPUT]:
        options[CulebraOptions.OUTPUT] = a
    elif o in ['A', CulebraOptions.INTERACTIVE]:
        options[CulebraOptions.INTERACTIVE] = True
    elif o in ['p', CulebraOptions.APPEND_TO_SYS_PATH]:
        options[CulebraOptions.APPEND_TO_SYS_PATH] = True
    elif o in ['s', CulebraOptions.SAVE_SCREENSHOT]:
        options[CulebraOptions.SAVE_SCREENSHOT] = a
    elif o in ['W', CulebraOptions.SAVE_VIEW_SCREENSHOTS]:
        options[CulebraOptions.SAVE_VIEW_SCREENSHOTS] = a
    elif o in ['G', CulebraOptions.GUI]:
        options[CulebraOptions.GUI] = True
    elif o in ['u', CulebraOptions.DO_NOT_VERIFY_INITIAL_SCREEN_DUMP]:
        options[CulebraOptions.DO_NOT_VERIFY_INITIAL_SCREEN_DUMP] = True
    elif o in ['P', CulebraOptions.SCALE]:
        options[CulebraOptions.SCALE] = float(a)

if not (options[CulebraOptions.FIND_VIEWS_BY_ID] or options[CulebraOptions.FIND_VIEWS_WITH_TEXT] or options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]):
    if not options[CulebraOptions.VERBOSE_COMMENTS]:
        warnings.warn('All printing options disabled. Output will be empty.')
    else:
        warnings.warn('Only verbose comments will be printed')

device, serialno = ViewClient.connectToDeviceOrExit(**kwargs1)
if options[CulebraOptions.START_ACTIVITY]:
    device.startActivity(component=options[CulebraOptions.START_ACTIVITY])
vc = ViewClient(device, serialno, **kwargs2)
if options[CulebraOptions.OUTPUT]:
    sys.stdout = codecs.open(options[CulebraOptions.OUTPUT], mode='w', encoding='utf-8', errors='replace')
    import stat
    st = os.stat(options[CulebraOptions.OUTPUT])
    os.chmod(options[CulebraOptions.OUTPUT], st.st_mode | stat.S_IEXEC)

if options[CulebraOptions.UNIT_TEST_CLASS] or (not options[CulebraOptions.UNIT_TEST_METHOD]):
    printScriptHeader()

if options[CulebraOptions.UNIT_TEST_CLASS]:
    printUnittestImport()

if options[CulebraOptions.APPEND_TO_SYS_PATH]:
    printAppendToSysPath()

if options[CulebraOptions.UNIT_TEST_CLASS] or (not options[CulebraOptions.UNIT_TEST_METHOD]):
    print '''\
from com.dtmilano.android.viewclient import ViewClient, CulebraTestCase
'''

if options[CulebraOptions.UNIT_TEST_CLASS]:
    print '''
class CulebraTests(CulebraTestCase):

    @classmethod
    def setUpClass(cls):
        cls.kwargs1 = %s
        cls.kwargs2 = %s
        cls.options = %s

''' % (kwargs1, kwargs2, options),

    print '''\
    def preconditions(self):
        return True

    def %s(self):
        if not self.preconditions():
            self.fail('Preconditions failed')
        ''' % (options[CulebraOptions.UNIT_TEST_METHOD] if options[CulebraOptions.UNIT_TEST_METHOD] else 'testSomething')

    if options[CulebraOptions.SAVE_SCREENSHOT]:
        print '''\
        self.vc.writeImageToFile('%s')
        ''' % options[CulebraOptions.SAVE_SCREENSHOT]
    
    if options[CulebraOptions.USE_DICTIONARY]:
        print '''\
        self.views = dict()'''

    vc.dump(window=options[CulebraOptions.WINDOW])
    indent = ' ' * 8
    prefix = 'self.'
    
    if not options[CulebraOptions.DO_NOT_VERIFY_INITIAL_SCREEN_DUMP]:
        print '''\
        self.vc.dump(%s)
        ''' % getWindowOption()
        vc.traverse(transform=transform)
        print

    if options[CulebraOptions.GUI]:
        runCulebron()

    print '''

if __name__ == '__main__':
    CulebraTests.main()
'''
else:
    if not options[CulebraOptions.UNIT_TEST_METHOD]:
        print '''
kwargs1 = %s
device, serialno = ViewClient.connectToDeviceOrExit(**kwargs1)
''' % kwargs1,

    if options[CulebraOptions.START_ACTIVITY] and not options[CulebraOptions.UNIT_TEST_METHOD]:
        print '''\
device.startActivity(component='%s')''' % options[CulebraOptions.START_ACTIVITY]

    if not options[CulebraOptions.UNIT_TEST_METHOD]:
        print '''\
kwargs2 = %s
vc = ViewClient(device, serialno, **kwargs2)
vc.dump(window=%s)
''' % (kwargs2, getWindowOption())

        if options[CulebraOptions.USE_DICTIONARY]:
            print '''views = dict()'''

        if options[CulebraOptions.SAVE_SCREENSHOT]:
            print '''\
vc.writeImageToFile('%s')
''' % options[CulebraOptions.SAVE_SCREENSHOT]
    
    vc.dump(window=options[CulebraOptions.WINDOW])
    if options[CulebraOptions.UNIT_TEST_METHOD]:
        print '''
    def %s(self):
        \'\'\'
        Test method.
        \'\'\'

        if not self.preconditions():
            self.fail('Preconditions failed')
''' % (options[CulebraOptions.UNIT_TEST_METHOD])
        indent = ' ' * 8
        prefix = 'self.'
    vc.traverse(transform=transform)

if options[CulebraOptions.INTERACTIVE]:
    import socket
    HOST = 'localhost'
    PORT = 8900
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    s.sendall("RECORD EVENTS START\n")
    fin = open("/dev/tty")
    while True:
        print >> sys.stderr, "Reading events..."
        data = s.recv(1024)
        code = ViewClient.excerpt(data)
        exec code
        resp = raw_input("Continue recording events? [Y/n]: ")
        if resp in ['N', 'n']:
            break
    s.sendall("RECORD EVENTS STOP\n")
    s.close()

