/*
 * 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.adb;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import com.android.ddmlib.IDevice;
import com.android.ddmlib.InstallException;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.TimeoutException;
import com.android.ddmlib.AdbCommandRejectedException;
import com.android.monkeyrunner.MonkeyDevice;
import com.android.monkeyrunner.MonkeyImage;
import com.android.monkeyrunner.MonkeyManager;
import com.android.monkeyrunner.adb.LinearInterpolator.Point;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nullable;

public class AdbMonkeyDevice extends MonkeyDevice {
    private static final Logger LOG = Logger.getLogger(AdbMonkeyDevice.class.getName());

    private static final String[] ZERO_LENGTH_STRING_ARRAY = new String[0];
    private static final long MANAGER_CREATE_TIMEOUT_MS = 5 * 1000; // 5 seconds

    private final ExecutorService executor = Executors.newCachedThreadPool();

    private final IDevice device;
    private MonkeyManager manager;

    public AdbMonkeyDevice(IDevice device) {
        this.device = device;
        this.manager = createManager("127.0.0.1", 12345);

        Preconditions.checkNotNull(this.manager);
    }

    @Override
    public MonkeyManager getManager() {
        return manager;
    }

    @Override
    public void dispose() {
        try {
            manager.quit();
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Error getting the manager to quit", e);
        }
        manager = null;
    }

    private void executeAsyncCommand(final String command,
            final LoggingOutputReceiver logger) {
        executor.submit(new Runnable() {
            public void run() {
                try {
                    device.executeShellCommand(command, logger);
                } catch (TimeoutException e) {
                    LOG.log(Level.SEVERE, "Error starting command: " + command, e);
                    throw new RuntimeException(e);
                } catch (AdbCommandRejectedException e) {
                    LOG.log(Level.SEVERE, "Error starting command: " + command, e);
                    throw new RuntimeException(e);
                } catch (ShellCommandUnresponsiveException e) {
                    LOG.log(Level.SEVERE, "Error starting command: " + command, e);
                    throw new RuntimeException(e);
                } catch (IOException e) {
                    LOG.log(Level.SEVERE, "Error starting command: " + command, e);
                    throw new RuntimeException(e);
                }
            }
        });
    }

    private MonkeyManager createManager(String address, int port) {
        try {
            device.createForward(port, port);
        } catch (TimeoutException e) {
            LOG.log(Level.SEVERE, "Timeout creating adb port forwarding", e);
            return null;
        } catch (AdbCommandRejectedException e) {
            LOG.log(Level.SEVERE, "Adb rejected adb port forwarding command: " + e.getMessage(), e);
            return null;
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Unable to create adb port forwarding: " + e.getMessage(), e);
            return null;
        }

        String command = "monkey --port " + port;
        executeAsyncCommand(command, new LoggingOutputReceiver(LOG, Level.FINE));

        // Sleep for a second to give the command time to execute.
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            LOG.log(Level.SEVERE, "Unable to sleep", e);
        }

        InetAddress addr;
        try {
            addr = InetAddress.getByName(address);
        } catch (UnknownHostException e) {
            LOG.log(Level.SEVERE, "Unable to convert address into InetAddress: " + address, e);
            return null;
        }

        // We have a tough problem to solve here.  "monkey" on the device gives us no indication
        // when it has started up and is ready to serve traffic.  If you try too soon, commands
        // will fail.  To remedy this, we will keep trying until a single command (in this case,
        // wake) succeeds.
        boolean success = false;
        MonkeyManager mm = null;
        long start = System.currentTimeMillis();

        while (!success) {
            long now = System.currentTimeMillis();
            long diff = now - start;
            if (diff > MANAGER_CREATE_TIMEOUT_MS) {
                LOG.severe("Timeout while trying to create monkey mananger");
                return null;
            }

            Socket monkeySocket;
            try {
                monkeySocket = new Socket(addr, port);
            } catch (IOException e) {
                LOG.log(Level.FINE, "Unable to connect socket", e);
                success = false;
                continue;
            }

            mm = new MonkeyManager(monkeySocket);

            try {
                mm.wake();
            } catch (IOException e) {
                LOG.log(Level.FINE, "Unable to wake up device", e);
                success = false;
                continue;
            }
            success = true;
        }

        return mm;
    }

    @Override
    public MonkeyImage takeSnapshot() {
        try {
            return new AdbMonkeyImage(device.getScreenshot());
        } catch (TimeoutException e) {
            LOG.log(Level.SEVERE, "Unable to take snapshot", e);
            return null;
        } catch (AdbCommandRejectedException e) {
            LOG.log(Level.SEVERE, "Unable to take snapshot", e);
            return null;
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Unable to take snapshot", e);
            return null;
        }
    }

    @Override
    protected String getSystemProperty(String key) {
        return device.getProperty(key);
    }

    @Override
    protected String getProperty(String key) {
        try {
            return manager.getVariable(key);
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Unable to get variable: " + key, e);
            return null;
        }
    }

    @Override
    protected void wake() {
        try {
            manager.wake();
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Unable to wake device (too sleepy?)", e);
        }
    }

    private String shell(String... args) {
        StringBuilder cmd = new StringBuilder();
        for (String arg : args) {
            cmd.append(arg).append(" ");
        }
        return shell(cmd.toString());
    }

    @Override
    protected String shell(String cmd) {
        CommandOutputCapture capture = new CommandOutputCapture();
        try {
            device.executeShellCommand(cmd, capture);
        } catch (TimeoutException e) {
            LOG.log(Level.SEVERE, "Error executing command: " + cmd, e);
            return null;
        } catch (ShellCommandUnresponsiveException e) {
            LOG.log(Level.SEVERE, "Error executing command: " + cmd, e);
            return null;
        } catch (AdbCommandRejectedException e) {
            LOG.log(Level.SEVERE, "Error executing command: " + cmd, e);
            return null;
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Error executing command: " + cmd, e);
            return null;
        }
        return capture.toString();
    }

    @Override
    protected boolean installPackage(String path) {
        try {
            String result = device.installPackage(path, true);
            if (result != null) {
                LOG.log(Level.SEVERE, "Got error installing package: "+ result);
                return false;
            }
            return true;
        } catch (InstallException e) {
            LOG.log(Level.SEVERE, "Error installing package: " + path, e);
            return false;
        }
    }

    @Override
    protected boolean removePackage(String packageName) {
        try {
            String result = device.uninstallPackage(packageName);
            if (result != null) {
                LOG.log(Level.SEVERE, "Got error uninstalling package "+ packageName + ": " +
                        result);
                return false;
            }
            return true;
        } catch (InstallException e) {
            LOG.log(Level.SEVERE, "Error installing package: " + packageName, e);
            return false;
        }
    }

    @Override
    protected void press(String keyName, TouchPressType type) {
        try {
            switch (type) {
                case DOWN_AND_UP:
                    manager.press(keyName);
                    break;
                case DOWN:
                    manager.keyDown(keyName);
                    break;
                case UP:
                    manager.keyUp(keyName);
                    break;
            }
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Error sending press event: " + keyName + " " + type, e);
        }
    }

    @Override
    protected void type(String string) {
        try {
            manager.type(string);
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Error Typing: " + string, e);
        }
    }

    @Override
    protected void touch(int x, int y, TouchPressType type) {
        try {
            switch (type) {
                case DOWN:
                    manager.touchDown(x, y);
                    break;
                case UP:
                    manager.touchUp(x, y);
                    break;
                case DOWN_AND_UP:
                    manager.tap(x, y);
                    break;
            }
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Error sending touch event: " + x + " " + y + " " + type, e);
        }
    }

    @Override
    protected void reboot(String into) {
        try {
            device.reboot(into);
        } catch (TimeoutException e) {
            LOG.log(Level.SEVERE, "Unable to reboot device", e);
        } catch (AdbCommandRejectedException e) {
            LOG.log(Level.SEVERE, "Unable to reboot device", e);
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Unable to reboot device", e);
        }
    }

    @Override
    protected void startActivity(String uri, String action, String data, String mimetype,
            Collection<String> categories, Map<String, Object> extras, String component,
            int flags) {
        List<String> intentArgs = buildIntentArgString(uri, action, data, mimetype, categories,
                extras, component, flags);
        shell(Lists.asList("am", "start",
                intentArgs.toArray(ZERO_LENGTH_STRING_ARRAY)).toArray(ZERO_LENGTH_STRING_ARRAY));
    }

    @Override
    protected void broadcastIntent(String uri, String action, String data, String mimetype,
            Collection<String> categories, Map<String, Object> extras, String component,
            int flags) {
        List<String> intentArgs = buildIntentArgString(uri, action, data, mimetype, categories,
                extras, component, flags);
        shell(Lists.asList("am", "broadcast",
                intentArgs.toArray(ZERO_LENGTH_STRING_ARRAY)).toArray(ZERO_LENGTH_STRING_ARRAY));
    }

    private static boolean isNullOrEmpty(@Nullable String string) {
        return string == null || string.length() == 0;
    }

    private List<String> buildIntentArgString(String uri, String action, String data, String mimetype,
            Collection<String> categories, Map<String, Object> extras, String component,
            int flags) {
        List<String> parts = Lists.newArrayList();

        // from adb docs:
        //<INTENT> specifications include these flags:
        //    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
        //    [-c <CATEGORY> [-c <CATEGORY>] ...]
        //    [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
        //    [--esn <EXTRA_KEY> ...]
        //    [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
        //    [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
        //    [-n <COMPONENT>] [-f <FLAGS>]
        //    [<URI>]

        if (!isNullOrEmpty(action)) {
            parts.add("-a");
            parts.add(action);
        }

        if (!isNullOrEmpty(data)) {
            parts.add("-d");
            parts.add(data);
        }

        if (!isNullOrEmpty(mimetype)) {
            parts.add("-t");
            parts.add(mimetype);
        }

        // Handle categories
        for (String category : categories) {
            parts.add("-c");
            parts.add(category);
        }

        // Handle extras
        for (Entry<String, Object> entry : extras.entrySet()) {
            // Extras are either boolean, string, or int.  See which we have
            Object value = entry.getValue();
            String valueString;
            String arg;
            if (value instanceof Integer) {
                valueString = Integer.toString((Integer) value);
                arg = "--ei";
            } else if (value instanceof Boolean) {
                valueString = Boolean.toString((Boolean) value);
                arg = "--ez";
            } else {
                // treat is as a string.
                valueString = value.toString();
                arg = "--esmake";
            }
            parts.add(arg);
            parts.add(valueString);
        }

        if (!isNullOrEmpty(component)) {
            parts.add("-n");
            parts.add(component);
        }

        if (flags != 0) {
            parts.add("-f");
            parts.add(Integer.toString(flags));
        }

        if (!isNullOrEmpty(uri)) {
            parts.add(uri);
        }

        return parts;
    }

    @Override
    protected Map<String, Object> instrument(String packageName, Map<String, Object> args) {
        List<String> shellCmd = Lists.newArrayList("am", "instrument", "-w", "-r", packageName);
        String result = shell(shellCmd.toArray(ZERO_LENGTH_STRING_ARRAY));
        return convertInstrumentResult(result);
    }

    /**
     * Convert the instrumentation result into it's Map representation.
     *
     * @param result the result string
     * @return the new map
     */
    @VisibleForTesting
    /* package */ static Map<String, Object> convertInstrumentResult(String result) {
        Map<String, Object> map = Maps.newHashMap();
        Pattern pattern = Pattern.compile("^INSTRUMENTATION_(\\w+): ", Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(result);

        int previousEnd = 0;
        String previousWhich = null;

        while (matcher.find()) {
            if ("RESULT".equals(previousWhich)) {
                String resultLine = result.substring(previousEnd, matcher.start()).trim();
                // Look for the = in the value, and split there
                int splitIndex = resultLine.indexOf("=");
                String key = resultLine.substring(0, splitIndex);
                String value = resultLine.substring(splitIndex + 1);

                map.put(key, value);
            }

            previousEnd = matcher.end();
            previousWhich = matcher.group(1);
        }
        if ("RESULT".equals(previousWhich)) {
            String resultLine = result.substring(previousEnd, matcher.start()).trim();
            // Look for the = in the value, and split there
            int splitIndex = resultLine.indexOf("=");
            String key = resultLine.substring(0, splitIndex);
            String value = resultLine.substring(splitIndex + 1);

            map.put(key, value);
        }
        return map;
    }

    @Override
    protected void drag(int startx, int starty, int endx, int endy, int steps, long ms) {
        final long iterationTime = ms / steps;

        LinearInterpolator lerp = new LinearInterpolator(steps);
        LinearInterpolator.Point start = new LinearInterpolator.Point(startx, starty);
        LinearInterpolator.Point end = new LinearInterpolator.Point(endx, endy);
        lerp.interpolate(start, end, new LinearInterpolator.Callback() {
            public void step(Point point) {
                try {
                    manager.touchMove(point.getX(), point.getY());
                } catch (IOException e) {
                    LOG.log(Level.SEVERE, "Error sending drag start event", e);
                }

                try {
                    Thread.sleep(iterationTime);
                } catch (InterruptedException e) {
                    LOG.log(Level.SEVERE, "Error sleeping", e);
                }
            }

            public void start(Point point) {
                try {
                    manager.touchDown(point.getX(), point.getY());
                } catch (IOException e) {
                    LOG.log(Level.SEVERE, "Error sending drag start event", e);
                }

                try {
                    Thread.sleep(iterationTime);
                } catch (InterruptedException e) {
                    LOG.log(Level.SEVERE, "Error sleeping", e);
                }
            }

            public void end(Point point) {
                try {
                    manager.touchUp(point.getX(), point.getY());
                } catch (IOException e) {
                    LOG.log(Level.SEVERE, "Error sending drag end event", e);
                }
            }
        });
    }
}
