/*
 * Copyright (C) 2010 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.monkeyrunner;

import com.google.common.base.Functions;
import com.google.common.base.Preconditions;
import com.google.common.collect.Collections2;

import com.android.monkeyrunner.doc.MonkeyRunnerExported;

import org.python.core.ArgParser;
import org.python.core.Py;
import org.python.core.PyDictionary;
import org.python.core.PyException;
import org.python.core.PyObject;
import org.python.core.PyTuple;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;

import javax.annotation.Nullable;

/*
 * Abstract base class that represents a single connected Android
 * Device and provides MonkeyRunner API methods for interacting with
 * that device.  Each backend will need to create a concrete
 * implementation of this class.
 */
public abstract class MonkeyDevice {
    /**
     * Create a MonkeyMananger for talking to this device.
     *
     * NOTE: This is not part of the jython API.
     *
     * @return the MonkeyManager
     */
    public abstract MonkeyManager getManager();

    /**
     * Dispose of any native resoureces this device may have taken hold of.
     *
     *  NOTE: This is not part of the jython API.
     */
    public abstract void dispose();

    @MonkeyRunnerExported(doc = "Fetch the screenbuffer from the device and return it.",
            returns = "The captured snapshot.")
    public abstract MonkeyImage takeSnapshot();

    @MonkeyRunnerExported(doc = "Get a MonkeyRunner property (like build.fingerprint)",
            args = {"key"},
            argDocs = {"The key of the property to return"},
            returns = "The value of the property")
    public String getProperty(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        return getProperty(ap.getString(0));
    }

    @MonkeyRunnerExported(doc = "Get a system property (returns the same value as getprop).",
            args = {"key"},
            argDocs = {"The key of the property to return"},
            returns = "The value of the property")
    public String getSystemProperty(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);
        return getSystemProperty(ap.getString(0));
    }

    @MonkeyRunnerExported(doc = "Enumeration of possible touch and press event types.  This gets " +
            "passed into a press or touch call to specify the event type.",
            argDocs = {"Indicates the down part of a touch/press event",
            "Indicates the up part of a touch/press event.",
            "Indicates that the monkey should send a down event immediately " +
                "followed by an up event"})
    public enum TouchPressType {
        DOWN, UP, DOWN_AND_UP
    }

    @MonkeyRunnerExported(doc = "Send a touch event at the specified location",
            args = { "x", "y", "type" },
            argDocs = { "x coordinate", "y coordinate", "the type of touch event to send"})
    public void touch(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        int x = ap.getInt(0);
        int y = ap.getInt(1);

        // Default
        MonkeyDevice.TouchPressType type = MonkeyDevice.TouchPressType.DOWN_AND_UP;
        try {
            PyObject pyObject = ap.getPyObject(2);
            type = (TouchPressType) pyObject.__tojava__(MonkeyDevice.TouchPressType.class);
        } catch (PyException e) {
            // bad stuff was passed in, just use the already specified default value
            type = MonkeyDevice.TouchPressType.DOWN_AND_UP;
        }
        touch(x, y, type);
    }

    @MonkeyRunnerExported(doc = "Simulate a drag on the screen.",
            args = { "start", "end", "duration", "steps"},
            argDocs = { "The starting point for the drag (a tuple of x,y)",
            "The end point for the drag (a tuple of x,y)",
            "How long (in seconds) should the drag take (default is 1.0 seconds)",
            "The number of steps to take when interpolating points. (default is 10)"})
    public void drag(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        PyObject startObject = ap.getPyObject(0);
        if (!(startObject instanceof PyTuple)) {
            throw Py.TypeError("Agrument 0 is not a tuple");
        }
        PyObject endObject = ap.getPyObject(1);
        if (!(endObject instanceof PyTuple)) {
            throw Py.TypeError("Agrument 1 is not a tuple");
        }

        PyTuple start = (PyTuple) startObject;
        PyTuple end = (PyTuple) endObject;

        int startx = (Integer) start.__getitem__(0).__tojava__(Integer.class);
        int starty = (Integer) start.__getitem__(1).__tojava__(Integer.class);
        int endx = (Integer) end.__getitem__(0).__tojava__(Integer.class);
        int endy = (Integer) end.__getitem__(1).__tojava__(Integer.class);

        double seconds = JythonUtils.getFloat(ap, 2, 1.0);
        long ms = (long) (seconds * 1000.0);

        int steps = ap.getInt(3, 10);

        drag(startx, starty, endx, endy, steps, ms);
    }

    @MonkeyRunnerExported(doc = "Send a key press event to the specified button",
            args = { "name", "type" },
            argDocs = { "the name of the key to press", "the type of touch event to send"})
    public void press(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        String name = ap.getString(0);

        // Default
        MonkeyDevice.TouchPressType type = MonkeyDevice.TouchPressType.DOWN_AND_UP;
        try {
            PyObject pyObject = ap.getPyObject(1);
            type = (TouchPressType) pyObject.__tojava__(MonkeyDevice.TouchPressType.class);
        } catch (PyException e) {
            // bad stuff was passed in, just use the already specified default value
            type = MonkeyDevice.TouchPressType.DOWN_AND_UP;
        }
        press(name, type);
    }

    @MonkeyRunnerExported(doc = "Type the specified string on the keyboard.",
            args = { "message" },
            argDocs = { "the message to type." })
    public void type(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        String message = ap.getString(0);
        type(message);
    }

    @MonkeyRunnerExported(doc = "Execute the given command on the shell.",
            args = { "cmd"},
            argDocs = { "The command to execute" },
            returns = "The output of the command")
    public String shell(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        String cmd = ap.getString(0);
        return shell(cmd);
    }

    @MonkeyRunnerExported(doc = "Reboot the specified device",
            args = { "into" },
            argDocs = { "the bootloader to reboot into (bootloader, recovery, or None)"})
    public void reboot(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        String into = ap.getString(0, null);

        reboot(into);
    }

    @MonkeyRunnerExported(doc = "Install the specified apk onto the device.",
            args = { "path" },
            argDocs = { "The path on the host filesystem to the APK to install." },
            returns = "True if install succeeded")
    public boolean installPackage(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        String path = ap.getString(0);
        return installPackage(path);
    }

    @MonkeyRunnerExported(doc = "Remove the specified package from the device.",
            args = { "package"},
            argDocs = { "The name of the package to uninstall"},
            returns = "'True if remove succeeded")
    public boolean removePackage(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        String packageName = ap.getString(0);
        return removePackage(packageName);
    }

    @MonkeyRunnerExported(doc = "Start the Activity specified by the intent.",
            args = { "uri", "action", "data", "mimetype", "categories", "extras",
                     "component", "flags" },
            argDocs = { "The URI for the intent",
                        "The action for the intent",
                        "The data URI for the intent",
                        "The mime type for the intent",
                        "The list of category names for the intent",
                        "A dictionary of extras to add to the intent.  Types of these extras " +
                            "are inferred from the python types of the values",
                        "The component of the intent",
                        "A list of flags for the intent" })
    public void startActivity(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        String uri = ap.getString(0, null);
        String action = ap.getString(1, null);
        String data = ap.getString(2, null);
        String mimetype = ap.getString(3, null);
        Collection<String> categories = Collections2.transform(JythonUtils.getList(ap, 4),
                Functions.toStringFunction());
        Map<String, Object> extras = JythonUtils.getMap(ap, 5);
        String component = ap.getString(6, null);
        int flags = ap.getInt(7, 0);

        startActivity(uri, action, data, mimetype, categories, extras, component, flags);
    }

    @MonkeyRunnerExported(doc = "Start the specified broadcast intent on the device.",
            args = { "uri", "action", "data", "mimetype", "categories", "extras",
                     "component", "flags" },
            argDocs = { "The URI for the intent",
                        "The action for the intent",
                        "The data URI for the intent",
                        "The mime type for the intent",
                        "The list of category names for the intent",
                        "A dictionary of extras to add to the intent.  Types of these extras " +
                            "are inferred from the python types of the values",
                        "The component of the intent",
                        "A list of flags for the intent" })
    public void broadcastIntent(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        String uri = ap.getString(0, null);
        String action = ap.getString(1, null);
        String data = ap.getString(2, null);
        String mimetype = ap.getString(3, null);
        Collection<String> categories = Collections2.transform(JythonUtils.getList(ap, 4),
                Functions.toStringFunction());
        Map<String, Object> extras = JythonUtils.getMap(ap, 5);
        String component = ap.getString(6, null);
        int flags = ap.getInt(7, 0);

        broadcastIntent(uri, action, data, mimetype, categories, extras, component, flags);
    }

    @MonkeyRunnerExported(doc = "Instrument the specified package and return the results from it.",
            args = { "className", "args" },
            argDocs = { "The class name to instrument (like com.android.test/.TestInstrument)",
                        "A Map of String to Objects for the aruments to pass to this " +
                        "instrumentation (default value is None)" },
            returns = "A map of string to objects for the results this instrumentation returned")
    public PyDictionary instrument(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        String packageName = ap.getString(0);
        Map<String, Object> instrumentArgs = JythonUtils.getMap(ap, 1);
        if (instrumentArgs == null) {
            instrumentArgs = Collections.emptyMap();
        }

        Map<String, Object> result = instrument(packageName, instrumentArgs);
        return JythonUtils.convertMapToDict(result);
    }

    @MonkeyRunnerExported(doc = "Wake up the screen on the device")
    public void wake(PyObject[] args, String[] kws) {
        ArgParser ap = JythonUtils.createArgParser(args, kws);
        Preconditions.checkNotNull(ap);

        wake();
    }

    /**
     * Reboot the device.
     *
     * @param into which bootloader to boot into.  Null means default reboot.
     */
    protected abstract void reboot(@Nullable String into);

    protected abstract String getProperty(String key);
    protected abstract String getSystemProperty(String key);
    protected abstract void touch(int x, int y, TouchPressType type);
    protected abstract void press(String keyName, TouchPressType type);
    protected abstract void drag(int startx, int starty, int endx, int endy, int steps, long ms);
    protected abstract void type(String string);
    protected abstract String shell(String cmd);
    protected abstract boolean installPackage(String path);
    protected abstract boolean removePackage(String packageName);
    protected abstract void startActivity(@Nullable String uri, @Nullable String action,
            @Nullable String data, @Nullable String mimetype,
            Collection<String> categories, Map<String, Object> extras, @Nullable String component,
            int flags);
    protected abstract void broadcastIntent(@Nullable String uri, @Nullable String action,
            @Nullable String data, @Nullable String mimetype,
            Collection<String> categories, Map<String, Object> extras, @Nullable String component,
            int flags);
    protected abstract Map<String, Object> instrument(String packageName,
            Map<String, Object> args);
    protected abstract void wake();
}
