# -*- coding:utf-8 -*-
from UAT_PathManage import UATPathManage
from ssat_sdk.UATree.UAT_tree import UATTree
from ssat_sdk.UATree.UAT_treeConstant import TreeConst
from UAT_runnerCommand import UATRunnerCommand
from ssat_sdk.python_uiautomator import PyUIAutomator, FocusManageAndroid, DirectionManageAndroid
from UAT_log import error, debug, info


import os, sys, time

DEBUG = True
INFO =True
ERROR = True
class UATRunner():
    cls = "UATRunner"
    def __init__(self):
        self.uatPathManage = UATPathManage()
        self.pyU = PyUIAutomator()
        self.dm = DirectionManageAndroid()
        self.fm = FocusManageAndroid(self.pyU, self.dm)
        self.runnerCmd = UATRunnerCommand(self.uatPathManage, self.pyU, self.dm, self.fm)
        # setOptionValue之后需要一个退回的pathlist来退出菜单
        self.executedPath = []

    '''
     当电视重启以后,uiautomator连接会断开,需要重新赋予UATRunner一个可用的连接对象
    '''
    def rebuildUiAutomator(self, pyUIAutomator, directionManageAndroid, focusManageAndroid):
        self.pyU = pyUIAutomator
        self.dm = directionManageAndroid
        self.fm = focusManageAndroid
        self.runnerCmd = UATRunnerCommand(self.uatPathManage, self.pyU, self.dm, self.fm)

    '''
    返回option的object
    '''
    def getOptionObject(self, option):
        className = option[UATTree.TAB_OPTION_VIEW][UATTree.View_Class]
        desc = option[UATTree.TAB_OPTION_VIEW][UATTree.View_Desc]
        resId = option[UATTree.TAB_OPTION_VIEW][UATTree.View_ID]
        text = option[UATTree.TAB_OPTION_VIEW][UATTree.View_Text]
        return self.pyU.getUiObject(className=className, resourceId=resId, description=desc, text=text)

    '''
    根据parent的layout和一个option判断在 UATree中的哪个界面,或者还没有进入UATree界面中
    :param option:目标option,表示在focusOption的路径上寻找界面定位。则根据excel分表查找
    :return parent数据,或者None。None代表未进入UATree界面中
    '''
    def locateParentUI(self, option=None):
        reg = ""
        if option is not None:
            print "locateParentUI,option:",option[UATTree.TAB_NAME]
            oname = option[UATTree.TAB_NAME]
            reg = oname.split("_")[0]
            print "locateParentUI,reg=",reg
        cparent = None
        treeDict = self.uatPathManage.uatData.getTreeDict()
        # print "locateParentUI: treeDict levels:",treeDict.keys()
        parentList = []
        levelList = treeDict.keys()
        flag = False
        for index in range(levelList.__len__()-1, -1, -1):
            level = levelList[index]
            # print "locateParentUI,level:", index, level
            levelDict = treeDict[level]
            for parent in levelDict:
                if reg.__len__() >0 and not parent.startswith(reg):
                    continue
                parentDict = levelDict[parent]
                layout = parentDict["layout"]
                # print "locateParentUI: layout:", layout
                ret = self.runnerCmd.checkParentChoose(parentDict)
                if ret > 0:
                    cparent = parentDict
                    flag = True
                    break
            if flag == True:
                break

        if cparent is None:
            info(self.cls, "locateParentUI", "没有选中Parent,电视界面不知道在哪里", INFO)
        else:
            info(self.cls, "locateParentUI", "选中Parent:" + cparent[UATTree.TAB_NAME], INFO)
        # print "ParentParam:", cparent
        return cparent

    '''
    在该option所在页面下,聚焦到目标option
    '''
    def moveToOption(self, option):
        parent = self.uatPathManage.uatData.getParentByOption(option)
        return self.runnerCmd.focusTargetOption(parent, option)

    '''
    :return -1 执行失败,放弃重新定位执行;0 执行失败,重新定位执行; 1 执行成功
    '''
    def runForwardPath(self, backPath, forwardPath):
        fLen = forwardPath.__len__()
        fParent = forwardPath[fLen-1]
        # 当backPath和forwardPath的父交点为first层时,不能走shortcut_key,否则会导致执行出现问题(USB界面)
        if fParent[UATTree.TAB_LEVEL] == "first" \
                and backPath.__len__() < 2:
            ret = self.openFirstParent(fParent, forwardPath)
            if ret < 1: #注意打开firstparent界面成功,定位错误,会重新定位。场景:usb
                return ret
            # 逐步进入后面的parent页面
            else:
                ret = self.goMidPath(fParent, forwardPath[1: fLen- 1])
            if ret is False:
                return -1
            #在目标parent中,选中目标option
            return self.moveToOption(forwardPath[0])
        else:
            ret = self.goMidPath(forwardPath[fLen - 1], forwardPath[1:fLen - 1])
            if ret is False:
                return -1
            # 在目标parent中,选中目标option
            return self.moveToOption(forwardPath[0])

    '''
    打开第一个页面
    :return: -1 代表activity打开失败,0 代表activity打开成功,焦点不在parent layout中;1 表示页面打开成功,焦点在parent layout中
            -2 表示处理弹窗的过程中失败了
    '''
    def openFirstParent(self, fParent, forwardPath):
        info(self.cls, "openFirstParent", "GOTO first parent " + fParent[UATTree.TAB_NAME], INFO)
        flag = self.runnerCmd.executeShortCutKey(fParent)
        if flag is False:
            error(self.cls, "openFirstParent", "Open first parent%s fail."%(fParent[UATTree.TAB_NAME]), ERROR)
            return -1
        ret = self.runnerCmd.executeDialog(fParent)
        if ret < 1:
            return -2
        flag1 = self.runnerCmd.checkParentChoose(fParent)
        if flag1 < 1:
            error(self.cls, "openFirstParent", "Open first parent activity.But parent %s not foucsed." % (fParent[UATTree.TAB_NAME]), ERROR)
            return 0
        return 1

    def goMidPath(self, curParent, midParentList):
        mLen = midParentList.__len__()
        for index in range(mLen-1, -1, -1):
            parent = midParentList[index]
            info(self.cls, "goMidPath", "GOTO parent %s from parent %s "%(parent[UATTree.TAB_NAME], curParent[UATTree.TAB_NAME]), INFO)
            ret = self.gotoNextParent(curParent, parent, midParentList)
            if ret == 0:
                return False
            curParent = parent
        return True

    '''
    :return 0:代表失败;1代表enterKey发送成功,进入下一个界面
    '''
    def gotoNextParent(self, curParent, targetParent, parentList):
        targetOptionName = targetParent[UATTree.TAB_NAME]
        targetOption = curParent[UATTree.TAB_OPTION][targetOptionName]
        flag = self.moveToOption(targetOption)
        if flag is False:
            return 0
        info(self.cls, "gotoNextParent", "moveToOption:%s done! executing enter key!"%targetOption[UATTree.TAB_NAME], INFO)
        ret = self.runnerCmd.executeEnterKey(targetOption[UATTree.TAB_ENTER_KEY], nextParent=targetParent)
        if ret is False:
            error(self.cls, "gotoNextParent",
                  "Send parent %s enter key fail." % (curParent[UATTree.TAB_NAME]), ERROR)
            return 0
        else:
            ret = self.runnerCmd.executeDialog(targetParent)
            return ret


    '''
    执行backPath
    :return true成功,false失败
    '''
    def runBackPath(self, backPath):
        bLen = backPath.__len__()
        if bLen <= 1:
            return False
        if bLen == 2:
            return True
        for index in range(1, bLen-1):
            curParent = backPath[index]
            prevParent = backPath[index+1]
            info(self.cls, "runBackPath", "back to parent %s from parent %s."
                 %(backPath[index][UATTree.TAB_NAME], backPath[index+1][UATTree.TAB_NAME]), INFO)
            flag = self.backToPrevParent(curParent, prevParent)
            if flag is False:
                return False
        return True

    def backToPrevParent(self, curParent, targetParent):
        backKeys = curParent[UATTree.TAB_TOPARENT_KEY]
        self.runnerCmd.executeKey(backKeys)
        dialog_A = curParent[UATTree.TAB_UI_VIEW][UATTree.UIView_Dialog_B]
        if dialog_A.__len__() > 0:
            ret = self.runnerCmd.executeDialog(curParent, isForward=False)
            if ret == 0:
                return False
        flag = self.runnerCmd.checkParentChoose(targetParent)
        if flag < 1:
            error(self.cls, "backToPrevParent",
                  "back to parent %s from parent %s fail." % (targetParent[UATTree.TAB_NAME], curParent[UATTree.TAB_NAME]), ERROR)
            return False
        return True

    '''
    fromFirst:表示是否指定从FirstParent打开开始路径执行。
    count:递归控制变量,执行路径的最大尝试次数
    '''
    def focusOption(self, option, fromFirst, count = 0):
        info(self.cls, "focusOption", "fromFirst:"+str(fromFirst), INFO)
        if fromFirst is True:
            curParent = None
        else:
            curParent = self.locateParentUI(option)
        backPath,forwardPath = self.uatPathManage.genOptionSmartPath(curParent, option)
        info(self.cls,"focusOption", "backPath:", INFO)
        self.uatPathManage.info(backPath)
        info(self.cls,"focusOption", "forwardPath:", INFO)
        self.uatPathManage.info(forwardPath)
        if forwardPath.__len__() == 0:
            return False
        if backPath.__len__() == 0 and forwardPath.__len__() >= 2:
            info(self.cls, "focusOption", "runBackPath success", INFO)
            ret = self.runForwardPath(backPath, forwardPath)
            self.executedPath = self.getExecutedPath(forwardPath)
            if ret ==0: #重新计算路径执行
                if count < 3:
                    return self.focusOption(option, fromFirst, count+1)
                else:
                    info(self.cls, "focusOption", "runForwardPath fail %s times, focusOption Fail!!!"%count, INFO)
                    return False
        if backPath.__len__() >= 2 and forwardPath.__len__() >=2:
            backFlag = self.runBackPath(backPath)
            if backFlag is False:
                info(self.cls, "focusOption", "runBackPath fail", INFO)
                return False
            info(self.cls, "focusOption", "runBackPath success", INFO)
            goFlag = self.runForwardPath(backPath, forwardPath)
            self.executedPath = self.getExecutedPath(forwardPath)
            if goFlag < 1:
                info(self.cls, "focusOption", "runForwardPath fail", INFO)
                return False
        info(self.cls, "focusOption", "runForwardPath success", INFO)
        return True

    '''
    for exitMenuByPath
    回退路径,仅仅只是使用forwardPath的话,最后一个元素是option,但是实际上已经进入了这个界面,应该判断的是parent。
    所以要把forwardPath里面的option替换为parent;如果没有配这个option对应的parent,则去掉该option,以便exitMenuByPath函数使用。
    '''
    def getExecutedPath(self, forwardPath):
        option = forwardPath[0]
        parentName = option[UATTree.TAB_NAME]
        parent = self.uatPathManage.uatData.getParentDict(parentName)
        if parent is None:
            forwardPath.remove(option)
        else:
            forwardPath[0] = parent
        return forwardPath
    '''
    执行该option的EnterKey
    '''
    def sendOptionEnterKey(self, option):
        enterKey = option[UATTree.TAB_ENTER_KEY]
        return self.runnerCmd.executeEnterKey(enterKey)

    '''
    检查当前页面是否存在目标option
    '''
    def checkOptionExist(self, option):
        parent = self.uatPathManage.uatData.getParentByOption(option)
        if not self.runnerCmd.checkParentChoose(parent):
            return False
        return self.runnerCmd.checkOptionExist(option, parent)


    '''
    在focusOption基础上,执行目标option的enter_key
    '''
    def openOption(self, option, fromFirst, nextParent = None):
        info(self.cls, "openOption", "OptionName:"+option[UATTree.TAB_NAME], INFO)
        ret = self.focusOption(option, fromFirst)
        if ret is False:
            return False
        ret = self.runnerCmd.executeEnterKey(option[UATTree.TAB_ENTER_KEY], nextParent)
        info(self.cls, "openOption", "executeKey,ret:%s" % ret, INFO)
        parent = self.uatPathManage.uatData.getParentDict(option[UATTree.TAB_NAME])
        if parent is None:
            return ret
        else:
            return self.runnerCmd.executeDialog(parent)

    def openParent(self, parent, fromFirst):
        if parent[UATTree.TAB_LEVEL] == 'first':
            return self.openFirstParent(parent, "")
        else:
            prevOption = self.uatPathManage.uatData.getOption(parent[UATTree.TAB_NAME])
            return self.openOption(prevOption, fromFirst, nextParent=parent)

    def setOptionValue(self, option, value, exitMenu=True, fromFirst=True):
        ret = self.openOption(option, fromFirst)
        if ret is False:
            info(self.cls, "setOptionValue", "openOption过程执行失败!!!", INFO)
            if exitMenu is True:
                self.runnerCmd.exitMenuByPath(self.executedPath)
            return False
        ret1 = self.runnerCmd.setValue(option, value)
        if exitMenu is True:
            ret2 = self.runnerCmd.exitMenuByPath(self.executedPath)
        else:
            ret2 = True
        return (ret1 and ret2)



    def checkOptionInfoView(self, option, cmpText = "", cmpPic = ""):
        infoObj = self.getOptionInfoView(option)
        result, picPath, cutPicPath = self.runnerCmd.getUIObjPic(infoObj)
        if result is False:
            error(self.cls, "checkOptionInfoView", "Warning:option %s 截取infoView所在坐标图片失败!!!" % option["name"], ERROR)
            return -1, picPath, cutPicPath
        if cmpPic != "":
            result = self.runnerCmd.infoViewCmpPic(cmpPic, cutPicPath)
            return result, picPath, cutPicPath
        elif cmpText != "":
            result = self.runnerCmd.infoViewCmpText(cmpText, cutPicPath)
            return result, picPath, cutPicPath
        else:
            info(self.cls, "checkOptionInfoView", "未传入cmpText和cmpPic参数,仅检查infoView是否存在", INFO)
            if infoObj is None:
                error(self.cls, "checkOptionInfoView", "Warning:option %s 获取infoView失败!!!" % option["name"],
                      ERROR)
                return -1, picPath, cutPicPath
            else:
                info(self.cls, "checkOptionInfoView", "已识别到option %s的infoView" % option["name"], INFO)
                return 1, picPath, cutPicPath


    def getOptionInfoView(self, option):
        optionView = option[UATTree.TAB_INFO_VIEW]
        viewId = optionView[UATTree.View_ID]
        viewText = optionView[UATTree.View_Text]
        viewDesc = optionView[UATTree.View_Desc]
        viewClass = optionView[UATTree.View_Class]
        if viewId.__len__() == 0:
            return None
        infoObj = self.pyU.getUiObject(resourceId=viewId, text=viewText, className=viewClass, description=viewDesc)
        return infoObj








if __name__ == "__main__":
    uatRunner = UATRunner()
    option = uatRunner.uatPathManage.uatData.getOption("usb_video_h264-ac3")
    uatRunner.openOption(option, False)
    # print uatRunner.locateParentUI()
    # parent = uatRunner.uatPathManage.uatData.getParentDict("usb_bmp")
    # uatRunner.runnerCmd.checkParentChoose(parent)
    # print option
    # option = uatRunner.uatPathManage.uatData.getOption("usb_aac_option")
    # cmpPic = r"D:/SAT/tmp\1572432282.74_cutPic_[932, 548, 1812, 597].png"
    # result, picpath, cutPicPath = uatRunner.checkOptionInfoView(option, cmpPic=cmpPic)
    # uatRunner.moveToOption(option)
    # parent = uatRunner.locateParentUI()
    # print "locateParentUI,parent:", parent
    # option = uatRunner.uatPathManage.uatData.getOption("usb_brightness")
    # print uatRunner.setOptionValue(option, 50)