/*
 * Copyright 2011, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.commands.monkey;

import static com.android.commands.monkey.MonkeySourceNetwork.EARG;

import android.accessibilityservice.UiTestAutomationBridge;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserId;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import com.android.commands.monkey.MonkeySourceNetwork.CommandQueue;
import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommand;
import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommandReturn;

import dalvik.system.DexClassLoader;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Utility class that enables Monkey to perform view introspection when issued Monkey Network
 * Script commands over the network.
 */
public class MonkeySourceNetworkViews {
    protected static UiTestAutomationBridge sUiTestAutomationBridge;
    private static IPackageManager sPm =
            IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
    private static Map<String, Class<?>> sClassMap = new HashMap<String, Class<?>>();

    private static final String REMOTE_ERROR =
            "Unable to retrieve application info from PackageManager";
    private static final String CLASS_NOT_FOUND = "Error retrieving class information";
    private static final String NO_ACCESSIBILITY_EVENT = "No accessibility event has occured yet";
    private static final String NO_NODE = "Node with given ID does not exist";
    private static final String NO_CONNECTION = "Failed to connect to AccessibilityService, "
                                                + "try restarting Monkey";

    private static final Map<String, ViewIntrospectionCommand> COMMAND_MAP =
            new HashMap<String, ViewIntrospectionCommand>();

    /* Interface for view queries */
    private static interface ViewIntrospectionCommand {
        /**
         * Get the response to the query
         * @return the response to the query
         */
        public MonkeyCommandReturn query(AccessibilityNodeInfo node, List<String> args);
    }

    static {
        COMMAND_MAP.put("getlocation", new GetLocation());
        COMMAND_MAP.put("gettext", new GetText());
        COMMAND_MAP.put("getclass", new GetClass());
        COMMAND_MAP.put("getchecked", new GetChecked());
        COMMAND_MAP.put("getenabled", new GetEnabled());
        COMMAND_MAP.put("getselected", new GetSelected());
        COMMAND_MAP.put("setselected", new SetSelected());
        COMMAND_MAP.put("getfocused", new GetFocused());
        COMMAND_MAP.put("setfocused", new SetFocused());
        COMMAND_MAP.put("getparent", new GetParent());
        COMMAND_MAP.put("getchildren", new GetChildren());
        COMMAND_MAP.put("getaccessibilityids", new GetAccessibilityIds());
    }

    /**
     * Registers the event listener for AccessibilityEvents.
     * Also sets up a communication connection so we can query the
     * accessibility service.
     */
    public static void setup() {
        sUiTestAutomationBridge = new UiTestAutomationBridge();
        sUiTestAutomationBridge.connect();
    }

    /**
     * Get the ID class for the given package.
     * This will cause issues if people reload a package with different
     * resource identifiers, but don't restart the Monkey server.
     *
     * @param packageName The package that we want to retrieve the ID class for
     * @return The ID class for the given package
     */
    private static Class<?> getIdClass(String packageName, String sourceDir)
            throws ClassNotFoundException {
        // This kind of reflection is expensive, so let's only do it
        // if we need to
        Class<?> klass = sClassMap.get(packageName);
        if (klass == null) {
            DexClassLoader classLoader = new DexClassLoader(
                    sourceDir, "/data/local/tmp",
                    null, ClassLoader.getSystemClassLoader());
            klass = classLoader.loadClass(packageName + ".R$id");
            sClassMap.put(packageName, klass);
        }
        return klass;
    }

    private static String getPositionFromNode(AccessibilityNodeInfo node) {
        Rect nodePosition = new Rect();
        node.getBoundsInScreen(nodePosition);
        StringBuilder positions = new StringBuilder();
        positions.append(nodePosition.left).append(" ").append(nodePosition.top);
        positions.append(" ").append(nodePosition.right-nodePosition.left).append(" ");
        positions.append(nodePosition.bottom-nodePosition.top);
        return positions.toString();
    }


    /**
     * Converts a resource identifier into it's generated integer ID
     *
     * @param stringId the string identifier
     * @return the generated integer identifier.
     */
    private static int getId(String stringId, AccessibilityEvent event)
            throws MonkeyViewException {
        try {
            AccessibilityNodeInfo node = event.getSource();
            String packageName = node.getPackageName().toString();
            ApplicationInfo appInfo = sPm.getApplicationInfo(packageName, 0, UserId.myUserId());
            Class<?> klass;
            klass = getIdClass(packageName, appInfo.sourceDir);
            return klass.getField(stringId).getInt(null);
        } catch (RemoteException e) {
            throw new MonkeyViewException(REMOTE_ERROR);
        } catch (ClassNotFoundException e){
            throw new MonkeyViewException(e.getMessage());
        } catch (NoSuchFieldException e){
            throw new MonkeyViewException("No such node with given id");
        } catch (IllegalAccessException e){
            throw new MonkeyViewException("Private identifier");
        } catch (NullPointerException e) {
            // AccessibilityServiceConnection throws a NullPointerException if you hand it
            // an ID that doesn't exist onscreen
            throw new MonkeyViewException("No node with given id exists onscreen");
        }
    }

    private static AccessibilityNodeInfo getNodeByAccessibilityIds(
            String windowString, String viewString) {
        int windowId = Integer.parseInt(windowString);
        int viewId = Integer.parseInt(viewString);
        return sUiTestAutomationBridge.findAccessibilityNodeInfoByAccessibilityId(windowId,
                viewId);
    }

    private static AccessibilityNodeInfo getNodeByViewId(String viewId, AccessibilityEvent event)
            throws MonkeyViewException {
        int id = getId(viewId, event);
        return sUiTestAutomationBridge.findAccessibilityNodeInfoByViewId(
                UiTestAutomationBridge.ACTIVE_WINDOW_ID, UiTestAutomationBridge.ROOT_NODE_ID, id);
    }

    /**
     * Command to list all possible view ids for the given application.
     * This lists all view ids regardless if they are on screen or not.
     */
    public static class ListViewsCommand implements MonkeyCommand {
        //listviews
        public MonkeyCommandReturn translateCommand(List<String> command,
                                                    CommandQueue queue) {
            AccessibilityEvent lastEvent = sUiTestAutomationBridge.getLastAccessibilityEvent();
            if (lastEvent == null) {
                return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
            }
            AccessibilityNodeInfo node = lastEvent.getSource();
            /* Occasionally the API will generate an event with no source, which is essentially the
             * same as it generating no event at all */
            if (node == null) {
                return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
            }
            String packageName = node.getPackageName().toString();
            try{
                Class<?> klass;
                ApplicationInfo appInfo = sPm.getApplicationInfo(packageName, 0, UserId.myUserId());
                klass = getIdClass(packageName, appInfo.sourceDir);
                StringBuilder fieldBuilder = new StringBuilder();
                Field[] fields = klass.getFields();
                for (Field field : fields) {
                    fieldBuilder.append(field.getName() + " ");
                }
                return new MonkeyCommandReturn(true, fieldBuilder.toString());
            } catch (RemoteException e){
                return new MonkeyCommandReturn(false, REMOTE_ERROR);
            } catch (ClassNotFoundException e){
                return new MonkeyCommandReturn(false, CLASS_NOT_FOUND);
            }
        }
    }

    /**
     * A command that allows for querying of views. It takes an id type, the requisite ids,
     * and the command for querying the view.
     */
    public static class QueryViewCommand implements MonkeyCommand {
        //queryview [id type] [id(s)] [command]
        //queryview viewid button1 gettext
        //queryview accessibilityids 12 5 getparent
        public MonkeyCommandReturn translateCommand(List<String> command,
                                                    CommandQueue queue) {
            if (command.size() > 2) {
                if (!sUiTestAutomationBridge.isConnected()) {
                    return new MonkeyCommandReturn(false, NO_CONNECTION);
                }
                AccessibilityEvent lastEvent = sUiTestAutomationBridge.getLastAccessibilityEvent();
                if (lastEvent == null) {
                    return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
                }
                String idType = command.get(1);
                AccessibilityNodeInfo node;
                String viewQuery;
                List<String> args;
                if ("viewid".equals(idType)) {
                    try {
                        node = getNodeByViewId(command.get(2), lastEvent);
                        viewQuery = command.get(3);
                        args = command.subList(4, command.size());
                    } catch (MonkeyViewException e) {
                        return new MonkeyCommandReturn(false, e.getMessage());
                    }
                } else if (idType.equals("accessibilityids")) {
                    try {
                        node = getNodeByAccessibilityIds(command.get(2), command.get(3));
                        viewQuery = command.get(4);
                        args = command.subList(5, command.size());
                    } catch (NumberFormatException e) {
                        return EARG;
                    }
                } else {
                    return EARG;
                }
                if (node == null) {
                    return new MonkeyCommandReturn(false, NO_NODE);
                }
                ViewIntrospectionCommand getter = COMMAND_MAP.get(viewQuery);
                if (getter != null) {
                    return getter.query(node, args);
                } else {
                    return EARG;
                }
            }
            return EARG;
        }
    }

    /**
     * A command that returns the accessibility ids of the root view.
     */
    public static class GetRootViewCommand implements MonkeyCommand {
        // getrootview
        public MonkeyCommandReturn translateCommand(List<String> command,
                                                    CommandQueue queue) {
            AccessibilityEvent lastEvent = sUiTestAutomationBridge.getLastAccessibilityEvent();
            if (lastEvent == null) {
                return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
            }
            AccessibilityNodeInfo node = lastEvent.getSource();
            return (new GetAccessibilityIds()).query(node, new ArrayList<String>());
        }
    }

    /**
     * A command that returns the accessibility ids of the views that contain the given text.
     * It takes a string of text and returns the accessibility ids of the nodes that contain the
     * text as a list of integers separated by spaces.
     */
    public static class GetViewsWithTextCommand implements MonkeyCommand {
        // getviewswithtext [text]
        // getviewswithtext "some text here"
        public MonkeyCommandReturn translateCommand(List<String> command,
                                                    CommandQueue queue) {
            if (!sUiTestAutomationBridge.isConnected()) {
                return new MonkeyCommandReturn(false, NO_CONNECTION);
            }
            if (command.size() == 2) {
                String text = command.get(1);
                List<AccessibilityNodeInfo> nodes = sUiTestAutomationBridge
                    .findAccessibilityNodeInfosByText(UiTestAutomationBridge.ACTIVE_WINDOW_ID,
                            UiTestAutomationBridge.ROOT_NODE_ID, text);
                ViewIntrospectionCommand idGetter = new GetAccessibilityIds();
                List<String> emptyArgs = new ArrayList<String>();
                StringBuilder ids = new StringBuilder();
                for (AccessibilityNodeInfo node : nodes) {
                    MonkeyCommandReturn result = idGetter.query(node, emptyArgs);
                    if (!result.wasSuccessful()){
                        return result;
                    }
                    ids.append(result.getMessage()).append(" ");
                }
                return new MonkeyCommandReturn(true, ids.toString());
            }
            return EARG;
        }
    }

    /**
     * Command to retrieve the location of the given node.
     * Returns the x, y, width and height of the view, separated by spaces.
     */
    public static class GetLocation implements ViewIntrospectionCommand {
        //queryview [id type] [id] getlocation
        //queryview viewid button1 getlocation
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                Rect nodePosition = new Rect();
                node.getBoundsInScreen(nodePosition);
                StringBuilder positions = new StringBuilder();
                positions.append(nodePosition.left).append(" ").append(nodePosition.top);
                positions.append(" ").append(nodePosition.right-nodePosition.left).append(" ");
                positions.append(nodePosition.bottom-nodePosition.top);
                return new MonkeyCommandReturn(true, positions.toString());
            }
            return EARG;
        }
    }


    /**
     * Command to retrieve the text of the given node
     */
    public static class GetText implements ViewIntrospectionCommand {
        //queryview [id type] [id] gettext
        //queryview viewid button1 gettext
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                if (node.isPassword()){
                    return new MonkeyCommandReturn(false, "Node contains a password");
                }
                /* Occasionally we get a null from the accessibility API, rather than an empty
                 * string */
                if (node.getText() == null) {
                    return new MonkeyCommandReturn(true, "");
                }
                return new MonkeyCommandReturn(true, node.getText().toString());
            }
            return EARG;
        }
    }


    /**
     * Command to retrieve the class name of the given node
     */
    public static class GetClass implements ViewIntrospectionCommand {
        //queryview [id type] [id] getclass
        //queryview viewid button1 getclass
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                return new MonkeyCommandReturn(true, node.getClassName().toString());
            }
            return EARG;
        }
    }
    /**
     * Command to retrieve the checked status of the given node
     */
    public static class GetChecked implements ViewIntrospectionCommand {
        //queryview [id type] [id] getchecked
        //queryview viewid button1 getchecked
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                return new MonkeyCommandReturn(true, Boolean.toString(node.isChecked()));
            }
            return EARG;
        }
    }

    /**
     * Command to retrieve whether the given node is enabled
     */
    public static class GetEnabled implements ViewIntrospectionCommand {
        //queryview [id type] [id] getenabled
        //queryview viewid button1 getenabled
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                return new MonkeyCommandReturn(true, Boolean.toString(node.isEnabled()));
            }
            return EARG;
        }
    }

    /**
     * Command to retrieve whether the given node is selected
     */
    public static class GetSelected implements ViewIntrospectionCommand {
        //queryview [id type] [id] getselected
        //queryview viewid button1 getselected
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                return new MonkeyCommandReturn(true, Boolean.toString(node.isSelected()));
            }
            return EARG;
        }
    }

    /**
     * Command to set the selected status of the given node. Takes a boolean value as its only
     * argument.
     */
    public static class SetSelected implements ViewIntrospectionCommand {
        //queryview [id type] [id] setselected [boolean]
        //queryview viewid button1 setselected true
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 1) {
                boolean actionPerformed;
                if (Boolean.valueOf(args.get(0))) {
                    actionPerformed = node.performAction(AccessibilityNodeInfo.ACTION_SELECT);
                } else if (!Boolean.valueOf(args.get(0))) {
                    actionPerformed =
                            node.performAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
                } else {
                    return EARG;
                }
                return new MonkeyCommandReturn(actionPerformed);
            }
            return EARG;
        }
    }

    /**
     * Command to get whether the given node is focused.
     */
    public static class GetFocused implements ViewIntrospectionCommand {
        //queryview [id type] [id] getfocused
        //queryview viewid button1 getfocused
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                return new MonkeyCommandReturn(true, Boolean.toString(node.isFocused()));
            }
            return EARG;
        }
    }

    /**
     * Command to set the focus status of the given node. Takes a boolean value
     * as its only argument.
     */
    public static class SetFocused implements ViewIntrospectionCommand {
        //queryview [id type] [id] setfocused [boolean]
        //queryview viewid button1 setfocused false
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 1) {
                boolean actionPerformed;
                if (Boolean.valueOf(args.get(0))) {
                    actionPerformed = node.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
                } else if (!Boolean.valueOf(args.get(0))) {
                    actionPerformed = node.performAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
                } else {
                    return EARG;
                }
                return new MonkeyCommandReturn(actionPerformed);
            }
            return EARG;
        }
    }

    /**
     * Command to get the accessibility ids of the given node. Returns the accessibility ids as a
     * space separated pair of integers with window id coming first, followed by the accessibility
     * view id.
     */
    public static class GetAccessibilityIds implements ViewIntrospectionCommand {
        //queryview [id type] [id] getaccessibilityids
        //queryview viewid button1 getaccessibilityids
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                int viewId;
                try {
                    Class<?> klass = node.getClass();
                    Field field = klass.getDeclaredField("mAccessibilityViewId");
                    field.setAccessible(true);
                    viewId = ((Integer) field.get(node)).intValue();
                } catch (NoSuchFieldException e) {
                    return new MonkeyCommandReturn(false, NO_NODE);
                } catch (IllegalAccessException e) {
                    return new MonkeyCommandReturn(false, "Access exception");
                }
                String ids = node.getWindowId() + " " + viewId;
                return new MonkeyCommandReturn(true, ids);
            }
            return EARG;
        }
    }

    /**
     * Command to get the accessibility ids of the parent of the given node. Returns the
     * accessibility ids as a space separated pair of integers with window id coming first followed
     * by the accessibility view id.
     */
    public static class GetParent implements ViewIntrospectionCommand {
        //queryview [id type] [id] getparent
        //queryview viewid button1 getparent
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                AccessibilityNodeInfo parent = node.getParent();
                if (parent == null) {
                  return new MonkeyCommandReturn(false, "Given node has no parent");
                }
                return (new GetAccessibilityIds()).query(parent, new ArrayList<String>());
            }
            return EARG;
        }
    }

    /**
     * Command to get the accessibility ids of the children of the given node. Returns the
     * children's ids as a space separated list of integer pairs. Each of the pairs consists of the
     * window id, followed by the accessibility id.
     */
    public static class GetChildren implements ViewIntrospectionCommand {
        //queryview [id type] [id] getchildren
        //queryview viewid button1 getchildren
        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
                                         List<String> args) {
            if (args.size() == 0) {
                ViewIntrospectionCommand idGetter = new GetAccessibilityIds();
                List<String> emptyArgs = new ArrayList<String>();
                StringBuilder ids = new StringBuilder();
                int totalChildren = node.getChildCount();
                for (int i = 0; i < totalChildren; i++) {
                    MonkeyCommandReturn result = idGetter.query(node.getChild(i), emptyArgs);
                    if (!result.wasSuccessful()) {
                        return result;
                    } else {
                        ids.append(result.getMessage()).append(" ");
                    }
                }
                return new MonkeyCommandReturn(true, ids.toString());
            }
            return EARG;
        }
    }
}
