/*
 * 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");
  private static Logger logger = Logger.global;

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

  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 = "touch down " + x + "  " + y + "\r\n" + "touch up " + x + " " + y + "\r\n";

    recordCommand("Tapping: " + x + ", " + y);
    System.out.println("Tapping: " + x + ", " + y);
    boolean result = sendMonkeyEvent(command, true, false);
    recordResponse(monkeyResponse);
    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 = "key down " + key + "\r\n" + "key up " + key + "\r\n";

    recordCommand("Pressing: " + key);
    if (print)
      System.out.println("Pressing: " + key);
    boolean result = sendMonkeyEvent(command, print, false);
    recordResponse(monkeyResponse);
    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 {
    System.out.println("Typing: " + text);
    recordCommand("Typing: " + text);
    
    for (int i=0; i<text.length(); i++) {
      String command = "key down ";
      char c = text.charAt(i);
      if(Character.isDigit(c)) {
        command += "KEYCODE_" + c + "\n" + "key up KEYCODE_" + c + "\n";
      } else {
        command = "key down " + c + "\n" + "key up " + c + "\n";
      }

      if(!sendMonkeyEvent(command, false, false)) {
        System.out.println("\nERROR: Key not set \n");
        recordResponse("ERROR: Key not set");
      }

      // lets delay a bit after each input to ensure accuracy
      try {
        Thread.sleep(KEY_INPUT_DELAY);
      } catch (InterruptedException e) {
      }
    }
    System.out.println("MonkeyServer: OK");
    recordResponse("OK");

    return true;
  }
  
  /**
   * 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 {
    System.out.println("Getting var: " + name);
    return sendMonkeyEvent("getvar " + name + "\n");
  }

  /**
   * Function to get the list of static variables from the device
   */
  public static boolean listvar() throws IOException {
    System.out.println("List of vars:");
    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 {
    // split a command string into line driven protocol monkey understands
    String[] commands = command.trim().split("[\r\n|\r|\n]+");
    for (String subcommand: commands) {
      if (record)
        recordCommand(subcommand);
      logger.info("Monkey Command: " + subcommand + ".");
      
      // send a single command and get the response
      monkeyWriter.write(subcommand + "\n");
      monkeyWriter.flush();      
      monkeyResponse = monkeyReader.readLine();

      logger.info("Monkey Response: " + monkeyResponse + ".");      
      if (record)
        recordResponse(monkeyResponse);
      
      // if a command returns an error, abandon further commands and return
      if((monkeyResponse != null) && monkeyResponse.equals("ERROR")) {
        if (print)
          System.out.println("MonkeyServer: " + monkeyResponse);
        return false;
      }
    }
    if (monkeyResponse != null) {
      // all responses were not ERROR
      if(monkeyResponse.startsWith("OK"))
        if (print)
          System.out.println("MonkeyServer: " + monkeyResponse);
        return true;
    } else {
      // didn't get a final response...
      if (print)
        System.out.println("MonkeyServer: ??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();
      String[] commands = command.split("[\\r\\n]+");   // for formatting, text might have line ends
      for (String subcommand: commands) {
        monkeyRecorder.addInput(subcommand);
      }
    }
  }
  
  /**
   * 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 attributes to 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);
  }
}
