# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Implementations of the Navigator interface."""

from abc import abstractmethod, abstractproperty
import os
import time

from safetynet import Any, Dict, TypecheckMeta, List

from optofidelity.util import ADB, AskUserContinue, const_property

from .backend import DUTBackend

_script_dir = os.path.dirname(os.path.realpath(__file__))


class Navigator(object):
  """Backend class to navigate a device to open subjects and pages."""
  __metaclass__ = TypecheckMeta

  @property
  def state(self):
    """State information. (e.g. coordinates of detected buttons)"""
    return {}

  @state.setter
  def state(self, value):
    pass

  def SetUp(self):
    """SetUp the navigator to run on a device."""

  def Prepare(self):
    """Prepare the underlying device for a benchmark run."""

  def Verify(self):
    """Verify that the device is accessible for a benchmark run."""

  @abstractmethod
  def Open(self):
    """Open the subject."""

  @abstractmethod
  def Close(self):
    """Close the subject."""

  @abstractmethod
  def Reset(self):
    """Reset the underlying DUT.

    This is a last resort after issues with opening the subject. This 'should'
    return the DUT into a state where the subject can be opened again.
    """

  @abstractmethod
  def Cleanup(self):
    """Get device back into a clean state."""

  @abstractmethod
  def HasActivity(self, activity_name):
    """:returns bool: True if the activity can be opened."""

  @abstractmethod
  def OpenActivity(self, activity_name):
    """Open activity.

    :type activity_name: str
    """

  @abstractmethod
  def CloseActivity(self):
    """Close previously opened activity."""


class BaseNavigator(Navigator):
  """Basic implementation to keep track of the device state."""

  NEUTRAL_ACTIVITY = "neutral"
  """Name of neutral activity to go back to after benchmark."""

  def __init__(self):
    self._is_open = False
    self._current_activity = None

  @classmethod
  def FromConfig(cls, attributes, children, dut_backend):
    return cls()

  def Open(self):
    # if self._is_open:
    #   raise Exception("Subject already open.")
    self._Open()
    self._is_open = True

  def Close(self):
    # if not self._is_open:
    #   raise Exception("Subject has not been opened.")
    # if self._current_activity:
    #   raise Exception("Activity still open.")
    self._Close()
    self._is_open = False

  def Reset(self):
    self._Reset()
    self._is_open = False
    self._current_activity = None

  def Cleanup(self):
    if self._current_activity:
      self.CloseActivity()
    if self._is_open:
      self.Close()

  def OpenActivity(self, activity_name):
    # if not self._is_open:
    #   raise Exception("Can't open activity if subject has not been opened.")
    # if self._current_activity:
    #   raise Exception("Another activity is already open.")
    if not self.HasActivity(activity_name):
      raise ValueError("Unknown activity name '%s'" % activity_name)

    self._OpenActivity(activity_name)
    self._current_activity = activity_name

  def CloseActivity(self):
    """Close previously opened activity."""
    # if not self._current_activity:
    #   raise Exception("No activity open.")
    self._CloseActivity()
    self._current_activity = None

  def _Open(self):
    """Private implementation of Open"""

  def _Close(self):
    """Private implementation of Close"""

  def _Reset(self):
    """Private implementation of Reset"""

  def _OpenActivity(self, activity_name):
    """Private implementation of OpenActivity"""

  def _CloseActivity(self):
    """Private implementation of CloseActivity"""


class FakeNavigator(BaseNavigator):
  @classmethod
  def FromConfig(cls, attributes, children, dut_backend):
    return cls()

  def HasActivity(self, activity_name):
    return True


class ManualNavigator(FakeNavigator):
  @classmethod
  def FromConfig(cls, attributes, children, dut_backend):
    return cls()

  def _OpenActivity(self, activity_name):
    if self._current_activity != activity_name:
      AskUserContinue("Open the '%s' activity" % activity_name)
      self._current_activity = activity_name


class RobotNavigator(BaseNavigator):
  """A navigation backend that uses the robot and OCR/Icon Detection.

  This backend will use icon detection and OCR to navigate a device.
  The device is expected to be in a kiosk mode always running the benchmark app.
  """
  def __init__(self, dut_backend):
    """
    :type dut_backend: DUTBackend
    """
    super(RobotNavigator, self).__init__()
    self._dut_backend = dut_backend
    self._activity_targets = {}
    self._activity_coords = {}

  @classmethod
  def FromConfig(cls, attributes, children, dut_backend):
    self = cls(dut_backend)
    for child_name, parameters in children:
      if child_name == "activity":
        self.AddActivity(parameters["name"], parameters.get("text"),
                         parameters.get("icon"))
    return self

  @property
  def state(self):
    return {
      "activity_coords": self._activity_coords
    }

  @state.setter
  def state(self, value):
    self._activity_coords = value["activity_coords"]

  def AddActivity(self, name, text=None, icon=None):
    if text is None and icon is None:
      raise ValueError("Specify either 'text' or 'icon'")
    self._activity_targets[name] = (text, icon)

  def HasActivity(self, activity_name):
    return activity_name in self._activity_targets

  def SetUp(self):
    icons = {i: a for a, (w, i) in self._activity_targets.iteritems()
                  if i is not None}
    words = {w: a for a, (w, i) in self._activity_targets.iteritems()
                  if w is not None}
    center_x, center_y = (self._dut_backend.width / 2,
                          self._dut_backend.height / 2)
    self._dut_backend.Tap(center_x, center_y)
    if len(words):
      word_coords = self._dut_backend.DetectWords(words.keys())
      for word, coords in word_coords.iteritems():
        if coords is None:
          raise Exception("Cannot detect word '%s'" % (word,))
        self._activity_coords[words[word]] = coords

    for icon_file, activity in icons.iteritems():
      coords = self._dut_backend.DetectIcon(icon_file)
      if coords is None:
        raise Exception("Cannot detect icon '%s'" % (icon_file,))
      self._activity_coords[activity] = coords

  def Prepare(self):
    self._CloseActivity()

  def _Open(self):
    if len(self._activity_targets) != len(self._activity_coords):
      raise Exception("You need to run --setup before using this navigator.")

  def _Reset(self):
    self._CloseActivity()

  def _OpenActivity(self, activity_name):
    coords = self._activity_coords[activity_name]
    self._dut_backend.Tap(*coords)

  def _CloseActivity(self):
    if self.NEUTRAL_ACTIVITY  in self._activity_coords:
      coords = self._activity_coords[self.NEUTRAL_ACTIVITY]
      self._dut_backend.Tap(*coords)


class BaseADBNavigator(BaseNavigator):
  """Navigation backend that uses ADB.

  This backend will use the ADB command line tool to communicate with a device
  to invoke intents to navigate to test pages.
  """
  REMOTE_DIR = "/sdcard/crostouch"

  def __init__(self, adb_device, stay_alive=True):
    """
    :param str adb_device: Serial number of the adb device.
    """
    super(BaseADBNavigator, self).__init__()
    self._adb = ADB(adb_device)
    self._stay_alive = stay_alive
    self._activity_intents = {}

  def AddActivity(self, activity_name, intent_params):
    self._activity_intents[activity_name] = intent_params

  def HasActivity(self, activity_name):
    return activity_name in self._activity_intents

  def Verify(self):
    self._adb.WaitForDevice()

  def Prepare(self):
    self._Reset()

  def _Open(self):
    self._adb.PowerOn()
    self._adb.PutSetting("system", "screen_brightness", "255")

  def _OpenActivity(self, activity_name):
    self._adb.SendKey("KEYCODE_HOME")  # Wake up screen sending home key
    intent_params = self._activity_intents[activity_name]
    self._adb.StartActivity(**intent_params)
    time.sleep(1.0)  # Wait for activity to load

  def _Close(self):
    if self.HasActivity(self.NEUTRAL_ACTIVITY):
      intent_params = self._activity_intents[self.NEUTRAL_ACTIVITY]
      self._adb.StartActivity(**intent_params)
    self._adb.PutSetting("system", "screen_brightness", "0")
    if not self._stay_alive:
      self._adb.PowerOff()

  def _CloseActivity(self):
    self._adb.SendKey("KEYCODE_HOME")

  def _Reset(self):
    self._adb.SendKey("KEYCODE_HOME")
    self._Close()


class WebADBNavigator(BaseADBNavigator):
  """Navigation backend that uses ADB to navigate to websites.

  This backend will use the ADB command line tool to communicate with a device.
  It will upload the HTML files needed and open them in Chrome.
  """
  VIEW_ACTION = "android.intent.action.VIEW"

  def __init__(self, adb_device, component, stay_alive=False):
    """
    :param str adb_device: Serial number of the adb device.
    """
    super(WebADBNavigator, self).__init__(adb_device, stay_alive)
    self._component = component
    self._resources = []

  @classmethod
  def FromConfig(cls, attributes, children, dut_backend):
    stay_alive = attributes.get("stay-alive") in ("True", "true")
    self = cls(attributes["adb"], attributes["component"], stay_alive)
    for child_name, parameters in children:
      if child_name == "activity":
        activity_name = parameters["name"]
        html_file = parameters["file"]
        self.AddHTMLActivity(activity_name, html_file)
      if child_name == "resource":
        self._resources.append(parameters["file"])
    return self

  def SetUp(self):
    self._adb.ExecuteShell(["mkdir", "-p", self.REMOTE_DIR])
    for filename in self._resources:
      basename = os.path.basename(filename)
      remote_file = os.path.join(self.REMOTE_DIR, basename)
      self._adb.PushFile(filename, remote_file)

  def AddHTMLActivity(self, activity_name, html_file):
    self._resources.append(html_file)
    basename = os.path.basename(html_file)
    remote_file = os.path.join(self.REMOTE_DIR, basename)
    uri = "file://%s" % remote_file
    intent_params = dict(component=self._component, uri=uri)
    self.AddActivity(activity_name, intent_params)


class NativeADBNavigator(BaseADBNavigator):
  """Navigation backend that uses ADB to navigate to websites.

  This backend will use the ADB command line tool to communicate with a device.
  It will upload the HTML files needed and open them in Chrome.
  """

  def __init__(self, adb_device, apk_file, package_name, stay_alive=False):
    """
    :param str adb_device: Serial number of the adb device.
    """
    super(NativeADBNavigator, self).__init__(adb_device, stay_alive)
    self._apk_file = apk_file
    self._package_name = package_name

  @classmethod
  def FromConfig(cls, attributes, children, dut_backend):
    stay_alive = attributes.get("stay-alive") in ("True", "true")
    self = cls(attributes["adb"], attributes["apk"], attributes["package"],
               stay_alive)
    for child_name, parameters in children:
      if child_name == "activity":
        if "class-name" in parameters:
          component = self._package_name + "/." + parameters["class-name"]
          intent_params = dict(component=component, force_stop=True)
        else:
          intent_params = dict()
          for key in ("action", "component", "uri", "category"):
            if key in parameters:
              intent_params[key] = parameters[key]
          for flag in ("wait", "force_stop"):
            attrib = parameters.get(flag.replace("_", "-"))
            if attrib  in ("True", "true"):
              intent_params[flag] = True
            if attrib  in ("False", "false"):
              intent_params[flag] = False
        self.AddActivity(parameters["name"], intent_params)
    return self

  def SetUp(self):
    if self._adb.GetPackageVersion(self._package_name):
      self._adb.UninstallPackage(self._package_name)
    self._adb.InstallAPK(self._apk_file)

  def Verify(self):
    super(NativeADBNavigator, self).Verify()
    if not self._adb.GetPackageVersion(self._package_name):
      raise Exception("You have to run --setup before using this subject.")
