/*
 * Copyright (c) 2020. BoostTag E.I.R.L. Romell D.Z.
 * All rights reserved
 * porfile.romellfudi.com
 */

package com.romellfudi.ussdlibrary;

import android.accessibilityservice.AccessibilityService;
import android.os.Bundle;
import android.view.accessibility.AccessibilityNodeInfo;

import com.elvishew.xlog.XLog;
import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * @author Romell Dominguez
 * @version 1.1.c 27/09/2018
 * @since 1.0.a
 */
public class PayController {
    private static AccessibilityService myAccessibilityService;

    public static AccessibilityService getMyAccessibilityService() {
        return myAccessibilityService;
    }

    public static void setMyAccessibilityService(AccessibilityService accessibilityService) {
        myAccessibilityService = accessibilityService;
    }


    public static String getNowRootInActiveWindow() {
        String PageJson = "{}";
        AccessibilityNodeInfo node = getMyAccessibilityService().getRootInActiveWindow();
        if (node != null) {
            XLog.i("[getNowRootInActiveWindow]node.isVisibleToUser() 尝试获取---->" + node.isVisibleToUser());
            XLog.i("[getNowRootInActiveWindow]node.isEnabled() 尝试获取---->" + node.isEnabled());
            NodeInfoWrapper nodeInfoWrapper = traverseNode(node);
            Gson gson = new Gson();
            PageJson = gson.toJson(nodeInfoWrapper);
        }
        return PageJson;
    }

    public static void performActionEvent1(int hashCode, int action) {
        AccessibilityNodeInfo node = getMyAccessibilityService().getRootInActiveWindow();
        findNodeByHashCode(node, hashCode).performAction(action);
    }

    public static void performActionEvent2(int hashCode, int action, List<HashMap<String, Object>> list) {
        AccessibilityNodeInfo node = getMyAccessibilityService().getRootInActiveWindow();
        Bundle arguments = new Bundle();

        for (HashMap<String, Object> map : list) {
            String key = Objects.requireNonNull(map.get("key")).toString();
            String value = Objects.requireNonNull(map.get("value")).toString();
            if (Objects.equals(map.get("type"), "CharSequence")) {
                arguments.putCharSequence(key, value);
            }
            if (Objects.equals(map.get("type"), "Int")) {
                arguments.putInt(key, Integer.parseInt(value));
            }
        }
        findNodeByHashCode(node, hashCode).performAction(action, arguments);
    }

    public static void performGlobalAction(int action) {
        getMyAccessibilityService().performGlobalAction(action);
    }

    private static NodeInfoWrapper traverseNode(AccessibilityNodeInfo nodeInfo) {
        NodeInfoWrapper nodeInfoWrapper = new NodeInfoWrapper();
        nodeInfoWrapper.txt = nodeInfo.getText() != null ? nodeInfo.getText().toString() : "";
        nodeInfoWrapper.vId = nodeInfo.getViewIdResourceName();
        nodeInfoWrapper.cName = nodeInfo.getClassName().toString();
        nodeInfoWrapper.pName = nodeInfo.getPackageName().toString();
        nodeInfoWrapper.hashcode = nodeInfo.hashCode();
        nodeInfoWrapper.childCount = nodeInfo.getChildCount();
        nodeInfoWrapper.canOpenPopup = nodeInfo.canOpenPopup();
        nodeInfoWrapper.visibleToUser = nodeInfo.isVisibleToUser();
        nodeInfoWrapper.isEnabled = nodeInfo.isEnabled();
        nodeInfoWrapper.hintText = nodeInfo.getHintText() != null ? nodeInfo.getText().toString() : "";
        nodeInfoWrapper.isClickable = nodeInfo.isClickable();
        nodeInfoWrapper.isLongClickable = nodeInfo.isLongClickable();
        nodeInfoWrapper.isEditable = nodeInfo.isEditable();
        nodeInfoWrapper.isCheckable = nodeInfo.isCheckable();
        nodeInfoWrapper.isChecked = nodeInfo.isChecked();
        nodeInfoWrapper.focused = nodeInfo.isFocused();
        nodeInfoWrapper.scrollable = nodeInfo.isScrollable();
        nodeInfoWrapper.isSelected = nodeInfo.isSelected();
        nodeInfoWrapper.isAccessibilityFocused = nodeInfo.isAccessibilityFocused();
        nodeInfoWrapper.isContentInvalid = nodeInfo.isContentInvalid();
        nodeInfoWrapper.isContextClickable = nodeInfo.isContextClickable();
        nodeInfoWrapper.isDismissable = nodeInfo.isDismissable();
        nodeInfoWrapper.isFocusable = nodeInfo.isFocusable();
        nodeInfoWrapper.isFocused = nodeInfo.isFocused();
        nodeInfoWrapper.isHeading = nodeInfo.isHeading();
        nodeInfoWrapper.isImportantForAccessibility = nodeInfo.isImportantForAccessibility();
        nodeInfoWrapper.isMultiLine = nodeInfo.isMultiLine();
        nodeInfoWrapper.isPassword = nodeInfo.isPassword();
        nodeInfoWrapper.isScreenReaderFocusable = nodeInfo.isScreenReaderFocusable();
        nodeInfoWrapper.isScrollable = nodeInfo.isScrollable();
        nodeInfoWrapper.isShowingHintText = nodeInfo.isShowingHintText();
        nodeInfoWrapper.isTextEntryKey = nodeInfo.isTextEntryKey();
        nodeInfoWrapper.isVisibleToUser = nodeInfo.isVisibleToUser();


        List<NodeInfoWrapper> childNodes = new ArrayList<>();
        for (int i = 0; i < nodeInfo.getChildCount(); i++) {
            AccessibilityNodeInfo childNode = nodeInfo.getChild(i);
            if (childNode != null) {
                NodeInfoWrapper childNodeWrapper = traverseNode(childNode);
                childNodes.add(childNodeWrapper);
            }
        }
        nodeInfoWrapper.childNodes = childNodes;

        return nodeInfoWrapper;
    }

    private static AccessibilityNodeInfo findNodeByHashCode(AccessibilityNodeInfo rootNode, int targetHashCode) {
        if (rootNode == null) {
            return null;
        }

        if (rootNode.hashCode() == targetHashCode) {
            return rootNode;
        }

        int childCount = rootNode.getChildCount();
        for (int i = 0; i < childCount; i++) {
            AccessibilityNodeInfo childNode = rootNode.getChild(i);
            AccessibilityNodeInfo result = findNodeByHashCode(childNode, targetHashCode);
            if (result != null) {
                return result;
            }
        }

        return null;
    }

    private static class NodeInfoWrapper {
        public String txt;
        public String vId;
        public String cName;
        public String pName;
        public int hashcode;
        public int childCount;
        //用于判断节点是否可以打开弹出窗口（popup）canOpenPopup()方法用于判断给定的节点是否具有打开弹出窗口的能力
        public boolean canOpenPopup;
        //判断节点是否对用户可见
        public boolean visibleToUser;
        //判断节点是否启用
        public boolean isEnabled;
        public String hintText;
        //判断节点是否可点击
        public boolean isClickable;
        //判断节点是否可长按
        public boolean isLongClickable;
        //判断节点是否可编辑
        public boolean isEditable;
        //判断节点是否可选择
        public boolean isCheckable;
        //判断节点的选择状态
        public boolean isChecked;
        //判断节点是否具有焦点
        public boolean focused;
        //判断节点是否可滚动
        public boolean scrollable;

        public boolean isSelected;

        public boolean isAccessibilityFocused;
        public boolean isContentInvalid;
        public boolean isContextClickable;
        public boolean isDismissable;
        public boolean isFocusable;
        public boolean isFocused;
        public boolean isHeading;
        public boolean isImportantForAccessibility;
        public boolean isMultiLine;
        public boolean isPassword;
        public boolean isScreenReaderFocusable;
        public boolean isScrollable;
        public boolean isShowingHintText;
        public boolean isTextEntryKey;
        public boolean isTextSelectable;
        public boolean isVisibleToUser;
        public List<NodeInfoWrapper> childNodes;
    }
}
