/*
 * Copyright (C) 2009 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.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
import com.android.ddmlib.NullOutputReceiver;
import com.android.ddmlib.RawImage;
import com.android.ddmlib.Log.ILogOutput;
import com.android.ddmlib.Log.LogLevel;

import java.awt.image.BufferedImage;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.ImageIO;

/**
 *  MonkeyRunner is a host side application to control a monkey instance on a
 *  device. MonkeyRunner provides some useful helper functions to control the
 *  device as well as various other methods to help script tests. 
 */
public class MonkeyRunner {

  static String monkeyServer = "127.0.0.1";
  static int monkeyPort = 1080;
  static Socket monkeySocket = null;

  static IDevice monkeyDevice;

  static BufferedReader monkeyReader;
  static BufferedWriter monkeyWriter;
  static String monkeyResponse;

  static MonkeyRecorder monkeyRecorder;

  static String scriptName = null;
  
  // Obtain a suitable logger.
  private static Logger logger = Logger.getLogger("com.android.monkeyrunner");

  // delay between key events
  final static int KEY_INPUT_DELAY = 1000;
  
  // version of monkey runner
  final static String monkeyRunnerVersion = "0.31";

  // TODO: interface cmd; class xml tags; fix logger; test class/script

  public static void main(String[] args) throws IOException {

    // haven't figure out how to get below INFO...bad parent.  Pass -v INFO to turn on logging 
    logger.setLevel(Level.parse("WARNING"));  
    processOptions(args);
    
    logger.info("initAdb");
    initAdbConnection();
    logger.info("openMonkeyConnection");
    openMonkeyConnection();

    logger.info("start_script");
    start_script();
    
    logger.info("ScriptRunner.run");
    ScriptRunner.run(scriptName);
   
    logger.info("end_script");
    end_script();
    logger.info("closeMonkeyConnection");
    closeMonkeyConnection();  
  }

  /**
   *  Initialize an adb session with a device connected to the host
   * 
   */
  public static void initAdbConnection() {
    String adbLocation = "adb";
    boolean device = false;
    boolean emulator = false;
    String serial = null;

    AndroidDebugBridge.init(false /* debugger support */);

    try {
      AndroidDebugBridge bridge = AndroidDebugBridge.createBridge(
          adbLocation, true /* forceNewBridge */);

      // we can't just ask for the device list right away, as the internal thread getting
      // them from ADB may not be done getting the first list.
      // Since we don't really want getDevices() to be blocking, we wait here manually.
      int count = 0;
      while (bridge.hasInitialDeviceList() == false) {
        try {
          Thread.sleep(100);
          count++;
        } catch (InterruptedException e) {
          // pass
        }

        // let's not wait > 10 sec.
        if (count > 100) {
          System.err.println("Timeout getting device list!");
          return;
        }
      }

      // now get the devices
      IDevice[] devices = bridge.getDevices();

      if (devices.length == 0) {
        printAndExit("No devices found!", true /* terminate */);
      }

      monkeyDevice = null;

      if (emulator || device) {
        for (IDevice d : devices) {
          // this test works because emulator and device can't both be true at the same
          // time.
          if (d.isEmulator() == emulator) {
            // if we already found a valid target, we print an error and return.
            if (monkeyDevice != null) {
              if (emulator) {
                printAndExit("Error: more than one emulator launched!",
                    true /* terminate */);
              } else {
                printAndExit("Error: more than one device connected!",true /* terminate */);
              }
            }
            monkeyDevice = d;
          }
        }
      } else if (serial != null) {
        for (IDevice d : devices) {
          if (serial.equals(d.getSerialNumber())) {
            monkeyDevice = d;
            break;
          }
        }
      } else {
        if (devices.length > 1) {
          printAndExit("Error: more than one emulator or device available!",
              true /* terminate */);
        }
        monkeyDevice = devices[0];
      }

      monkeyDevice.createForward(monkeyPort, monkeyPort);
      String command = "monkey --port " + monkeyPort;
      monkeyDevice.executeShellCommand(command, new NullOutputReceiver());

    } catch(IOException e) {
      e.printStackTrace();
    }
  }

  /**
   * Open a tcp session over adb with the device to communicate monkey commands
   */
  public static void openMonkeyConnection() {
    try {
      InetAddress addr = InetAddress.getByName(monkeyServer);
      monkeySocket = new Socket(addr, monkeyPort);
      monkeyWriter = new BufferedWriter(new OutputStreamWriter(monkeySocket.getOutputStream()));
      monkeyReader = new BufferedReader(new InputStreamReader(monkeySocket.getInputStream()));
    } catch (UnknownHostException e) {
      e.printStackTrace();
    } catch(IOException e) {
      e.printStackTrace();
    }
  }
  
  /** 
   * Close tcp session with the monkey on the device
   * 
   */
  public static void closeMonkeyConnection() {
    try {
      monkeyReader.close();
      monkeyWriter.close();
      monkeySocket.close();
      AndroidDebugBridge.terminate();
    } catch(IOException e) {
      e.printStackTrace();
    }
  }

  /** 
   * This is a house cleaning routine to run before starting a script. Puts
   * the device in a known state and starts recording interesting info.
   */
  public static void start_script() throws IOException {
    press("menu", false);
    press("menu", false);
    press("home", false);
    
    // Start recording the script output, might want md5 signature of file for completeness
    monkeyRecorder = new MonkeyRecorder(scriptName);

    // Record what device and version of software we are running on
    monkeyRecorder.addAttribute("monkeyRunnerVersion", monkeyRunnerVersion);
    addDeviceVars();
    monkeyRecorder.addComment("Script commands");
  }

  /** 
   * This is a house cleaning routine to run after finishing a script.
   * Puts the monkey server in a known state and closes the recording.
   */
  public static void end_script() throws IOException {
    String command = "done";
    sendMonkeyEvent(command, false, false);
    
    // Stop the recording and zip up the results
    monkeyRecorder.close();
  }

  /** This is a method for scripts to launch an activity on the device
   * 
   * @param name The name of the activity to launch 
   */
  public static void launch_activity(String name) throws IOException {
    System.out.println("Launching: " + name);
    recordCommand("Launching: " + name);
    monkeyDevice.executeShellCommand("am start -a android.intent.action.MAIN -n " 
        + name, new NullOutputReceiver());
    // void return, so no response given, just close the command element in the xml file.
    monkeyRecorder.endCommand();
   }

  /**
   * Grabs the current state of the screen stores it as a png
   * 
   * @param tag filename or tag descriptor of the screenshot
   */
  public static void grabscreen(String tag) throws IOException {
    tag += ".png";

    try {
      Thread.sleep(1000);
      getDeviceImage(monkeyDevice, tag, false);
    } catch (InterruptedException e) {
    }
  }

  /**
   * Sleeper method for script to call
   * 
   * @param msec msecs to sleep for
   */
  public static void sleep(int msec) throws IOException {
    try {
      recordCommand("sleep: " + msec);
      Thread.sleep(msec);
      recordResponse("OK");
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  /**
   * Tap function for scripts to call at a particular x and y location
   * 
   * @param x x-coordinate
   * @param y y-coordinate
   */
  public static boolean tap(int x, int y) throws IOException {
    String command = "tap " + x + " " + y;
    boolean result = sendMonkeyEvent(command);
    return result;
  }

  /** 
   * Press function for scripts to call on a particular button or key
   * 
   * @param key key to press
   */
  public static boolean press(String key) throws IOException {
    return press(key, true);
  }

  /** 
   * Press function for scripts to call on a particular button or key
   * 
   * @param key key to press
   * @param print whether to send output to user
   */
  private static boolean press(String key, boolean print) throws IOException {
    String command = "press " + key;
    boolean result = sendMonkeyEvent(command, print, true);
    return result;
  }

  /**
   * dpad down function
   */
  public static boolean down() throws IOException {
    return press("dpad_down");
  }

  /**
   * dpad up function
   */
  public static boolean up() throws IOException {
    return press("dpad_up");
  }

  /**
   * Function to type text on the device
   * 
   * @param text text to type
   */
  public static boolean type(String text) throws IOException {
    boolean result = false;
    // text might have line ends, which signal new monkey command, so we have to eat and reissue
    String[] lines = text.split("[\\r\\n]+");
    for (String line: lines) {
      result = sendMonkeyEvent("type " + line + "\n");
    }
    // return last result.  Should never fail..?
    return result;
  }
  
  /**
   * Function to get a static variable from the device
   * 
   * @param name name of static variable to get
   */
  public static boolean getvar(String name) throws IOException {
    return sendMonkeyEvent("getvar " + name + "\n");
  }

  /**
   * Function to get the list of static variables from the device
   */
  public static boolean listvar() throws IOException {
    return sendMonkeyEvent("listvar \n");
  }

  /**
   * This function is the communication bridge between the host and the device.
   * It sends monkey events and waits for responses over the adb tcp socket.
   * This version if for all scripted events so that they get recorded and reported to user.
   * 
   * @param command the monkey command to send to the device
   */
  private static boolean sendMonkeyEvent(String command) throws IOException {
    return sendMonkeyEvent(command, true, true);
  }

  /**
   * This function allows the communication bridge between the host and the device
   * to be invisible to the script for internal needs.
   * It splits a command into monkey events and waits for responses for each over an adb tcp socket.
   * Returns on an error, else continues and sets up last response.
   * 
   * @param command the monkey command to send to the device
   * @param print whether to print out the responses to the user
   * @param record whether to put the command in the xml file that stores test outputs
   */
  private static boolean sendMonkeyEvent(String command, Boolean print, Boolean record) throws IOException {
    command = command.trim();
    if (print)
      System.out.println("MonkeyCommand: " + command);
    if (record)
      recordCommand(command);
    logger.info("Monkey Command: " + command + ".");
      
    // send a single command and get the response
    monkeyWriter.write(command + "\n");
    monkeyWriter.flush();
    monkeyResponse = monkeyReader.readLine();

    if(monkeyResponse != null) {
      // if a command returns with a response
      if (print)
        System.out.println("MonkeyServer: " + monkeyResponse);
      if (record)
        recordResponse(monkeyResponse);
      logger.info("Monkey Response: " + monkeyResponse + ".");

      // return on error
      if (monkeyResponse.startsWith("ERROR"))
        return false;

      // return on ok
      if(monkeyResponse.startsWith("OK"))
        return true;

      // return on something else?
      return false;
    }
    // didn't get a response...
    if (print)
      System.out.println("MonkeyServer: ??no response");
    if (record)
      recordResponse("??no response");
    logger.info("Monkey Response: ??no response.");

    //return on no response
    return false;
  }

  /**
   * Record the command in the xml file
   *
   * @param command the command sent to the monkey server
   */
  private static void recordCommand(String command) throws IOException {
    if (monkeyRecorder != null) {                       // don't record setup junk
      monkeyRecorder.startCommand();
      monkeyRecorder.addInput(command);
    }
  }
  
  /**
   * Record the response in the xml file
   *
   * @param response the response sent by the monkey server
   */
  private static void recordResponse(String response) throws IOException {
    recordResponse(response, "");
  } 
  
  /**
   * Record the response and the filename in the xml file, store the file (to be zipped up later)
   *
   * @param response the response sent by the monkey server
   * @param filename the filename of a file to be time stamped, recorded in the xml file and stored
   */
  private static void recordResponse(String response, String filename) throws IOException {
    if (monkeyRecorder != null) {                    // don't record setup junk
      monkeyRecorder.addResult(response, filename);  // ignores file if filename empty
      monkeyRecorder.endCommand();
    }
  }
    
  /**
   * Add the device variables to the xml file in monkeyRecorder.
   * The results get added as device_var tags in the script_run tag
   */
  private static void addDeviceVars() throws IOException {
    monkeyRecorder.addComment("Device specific variables");
    sendMonkeyEvent("listvar \n", false, false);
    if (monkeyResponse.startsWith("OK:")) {
      // peel off "OK:" string and get the individual var names  
      String[] varNames = monkeyResponse.substring(3).split("\\s+");
      // grab all the individual var values
      for (String name: varNames) {
        sendMonkeyEvent("getvar " + name, false, false);
        if(monkeyResponse != null) {
          if (monkeyResponse.startsWith("OK") ) {
            if (monkeyResponse.length() > 2) {
              monkeyRecorder.addDeviceVar(name, monkeyResponse.substring(3));
            } else { 
              // only got OK - good variable but no value
              monkeyRecorder.addDeviceVar(name, "null");
            }
          } else { 
            // error returned - couldn't get var value for name... include error return
            monkeyRecorder.addDeviceVar(name, monkeyResponse);
          }
        } else { 
          // no monkeyResponse - bad variable with no value
          monkeyRecorder.addDeviceVar(name, "null");
        }
      }
    } else {
      // it's an error, can't find variable names...
      monkeyRecorder.addAttribute("listvar", monkeyResponse);
    }
  }
  
  /**
   * Process the command-line options
   *
   * @return Returns true if options were parsed with no apparent errors.
   */
  private static void processOptions(String[] args) {
    // parse command line parameters.
    int index = 0;

    do {
      String argument = args[index++];

      if ("-s".equals(argument)) {
        if(index == args.length) {
          printUsageAndQuit("Missing Server after -s");
        }

        monkeyServer = args[index++];

      } else if ("-p".equals(argument)) {
        // quick check on the next argument.
        if (index == args.length) {
          printUsageAndQuit("Missing Server port after -p");
        }

        monkeyPort = Integer.parseInt(args[index++]);

      } else if ("-v".equals(argument)) {
        // quick check on the next argument.
        if (index == args.length) {
          printUsageAndQuit("Missing Log Level after -v");
        }

        Level level = Level.parse(args[index++]);
        logger.setLevel(level);
        level = logger.getLevel();
        System.out.println("Log level set to: " + level + "(" + level.intValue() + ").");
        System.out.println("Warning: Log levels below INFO(800) not working currently... parent issues");
        
      } else if (argument.startsWith("-")) {
        // we have an unrecognized argument.
        printUsageAndQuit("Unrecognized argument: " + argument + ".");

        monkeyPort = Integer.parseInt(args[index++]);

      } else {
        // get the filepath of the script to run.  This will be the last undashed argument.
        scriptName = argument;
      }
    } while (index < args.length);
  }

  /*
   * Grab an image from an ADB-connected device.
   */
  private static void getDeviceImage(IDevice device, String filepath, boolean landscape)
  throws IOException {
    RawImage rawImage;
    recordCommand("grabscreen");
    System.out.println("Grabbing Screeshot: " + filepath + ".");

    try {
      rawImage = device.getScreenshot();
    }
    catch (IOException ioe) {
      recordResponse("No frame buffer", "");
      printAndExit("Unable to get frame buffer: " + ioe.getMessage(), true /* terminate */);
      return;
    }

    // device/adb not available?
    if (rawImage == null) {
      recordResponse("No image", "");
      return;
    }
    
    assert rawImage.bpp == 16;

    BufferedImage image;
    
    logger.info("Raw Image - height: " + rawImage.height + ", width: " + rawImage.width);

    if (landscape) {
      // convert raw data to an Image
      image = new BufferedImage(rawImage.height, rawImage.width,
          BufferedImage.TYPE_INT_ARGB);

      byte[] buffer = rawImage.data;
      int index = 0;
      for (int y = 0 ; y < rawImage.height ; y++) {
        for (int x = 0 ; x < rawImage.width ; x++) {

          int value = buffer[index++] & 0x00FF;
          value |= (buffer[index++] << 8) & 0x0FF00;

          int r = ((value >> 11) & 0x01F) << 3;
          int g = ((value >> 5) & 0x03F) << 2;
          int b = ((value >> 0) & 0x01F) << 3;

          value = 0xFF << 24 | r << 16 | g << 8 | b;

          image.setRGB(y, rawImage.width - x - 1, value);
        }
      }
    } else {
      // convert raw data to an Image
      image = new BufferedImage(rawImage.width, rawImage.height,
          BufferedImage.TYPE_INT_ARGB);

      byte[] buffer = rawImage.data;
      int index = 0;
      for (int y = 0 ; y < rawImage.height ; y++) {
        for (int x = 0 ; x < rawImage.width ; x++) {

          int value = buffer[index++] & 0x00FF;
          value |= (buffer[index++] << 8) & 0x0FF00;

          int r = ((value >> 11) & 0x01F) << 3;
          int g = ((value >> 5) & 0x03F) << 2;
          int b = ((value >> 0) & 0x01F) << 3;

          value = 0xFF << 24 | r << 16 | g << 8 | b;

          image.setRGB(x, y, value);
        }
      }
    }

    if (!ImageIO.write(image, "png", new File(filepath))) {
      recordResponse("No png writer", "");
      throw new IOException("Failed to find png writer");
    }
    recordResponse("OK", filepath);
  }

  private static void printUsageAndQuit(String message) {
    // 80 cols marker:  01234567890123456789012345678901234567890123456789012345678901234567890123456789
    System.out.println(message);
    System.out.println("Usage: monkeyrunner [options] SCRIPT_FILE");
    System.out.println("");
    System.out.println("    -s      MonkeyServer IP Address.");
    System.out.println("    -p      MonkeyServer TCP Port.");
    System.out.println("    -v      MonkeyServer Logging level (ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF)");
    System.out.println("");
    System.out.println("");

    System.exit(1);
  }

  private static void printAndExit(String message, boolean terminate) {
    System.out.println(message);
    if (terminate) {
      AndroidDebugBridge.terminate();
    }
    System.exit(1);
  }
}
