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

"""Helper object to read and modify Shared Preferences from Android apps.

See e.g.:
  http://developer.android.com/reference/android/content/SharedPreferences.html
"""

import logging
import posixpath

from devil.android import device_errors
from devil.android.sdk import version_codes
from xml.etree import ElementTree

logger = logging.getLogger(__name__)


_XML_DECLARATION = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"


class BasePref(object):
  """Base class for getting/setting the value of a specific preference type.

  Should not be instantiated directly. The SharedPrefs collection will
  instantiate the appropriate subclasses, which directly manipulate the
  underlying xml document, to parse and serialize values according to their
  type.

  Args:
    elem: An xml ElementTree object holding the preference data.

  Properties:
    tag_name: A string with the tag that must be used for this preference type.
  """
  tag_name = None

  def __init__(self, elem):
    if elem.tag != type(self).tag_name:
      raise TypeError('Property %r has type %r, but trying to access as %r' %
                      (elem.get('name'), elem.tag, type(self).tag_name))
    self._elem = elem

  def __str__(self):
    """Get the underlying xml element as a string."""
    return ElementTree.tostring(self._elem)

  def get(self):
    """Get the value of this preference."""
    return self._elem.get('value')

  def set(self, value):
    """Set from a value casted as a string."""
    self._elem.set('value', str(value))

  @property
  def has_value(self):
    """Check whether the element has a value."""
    return self._elem.get('value') is not None


class BooleanPref(BasePref):
  """Class for getting/setting a preference with a boolean value.

  The underlying xml element has the form, e.g.:
      <boolean name="featureEnabled" value="false" />
  """
  tag_name = 'boolean'
  VALUES = {'true': True, 'false': False}

  def get(self):
    """Get the value as a Python bool."""
    return type(self).VALUES[super(BooleanPref, self).get()]

  def set(self, value):
    """Set from a value casted as a bool."""
    super(BooleanPref, self).set('true' if value else 'false')


class FloatPref(BasePref):
  """Class for getting/setting a preference with a float value.

  The underlying xml element has the form, e.g.:
      <float name="someMetric" value="4.7" />
  """
  tag_name = 'float'

  def get(self):
    """Get the value as a Python float."""
    return float(super(FloatPref, self).get())


class IntPref(BasePref):
  """Class for getting/setting a preference with an int value.

  The underlying xml element has the form, e.g.:
      <int name="aCounter" value="1234" />
  """
  tag_name = 'int'

  def get(self):
    """Get the value as a Python int."""
    return int(super(IntPref, self).get())


class LongPref(IntPref):
  """Class for getting/setting a preference with a long value.

  The underlying xml element has the form, e.g.:
      <long name="aLongCounter" value="1234" />

  We use the same implementation from IntPref.
  """
  tag_name = 'long'


class StringPref(BasePref):
  """Class for getting/setting a preference with a string value.

  The underlying xml element has the form, e.g.:
      <string name="someHashValue">249b3e5af13d4db2</string>
  """
  tag_name = 'string'

  def get(self):
    """Get the value as a Python string."""
    return self._elem.text

  def set(self, value):
    """Set from a value casted as a string."""
    self._elem.text = str(value)


class StringSetPref(StringPref):
  """Class for getting/setting a preference with a set of string values.

  The underlying xml element has the form, e.g.:
      <set name="managed_apps">
          <string>com.mine.app1</string>
          <string>com.mine.app2</string>
          <string>com.mine.app3</string>
      </set>
  """
  tag_name = 'set'

  def get(self):
    """Get a list with the string values contained."""
    value = []
    for child in self._elem:
      assert child.tag == 'string'
      value.append(child.text)
    return value

  def set(self, value):
    """Set from a sequence of values, each casted as a string."""
    for child in list(self._elem):
      self._elem.remove(child)
    for item in value:
      ElementTree.SubElement(self._elem, 'string').text = str(item)


_PREF_TYPES = {c.tag_name: c for c in [BooleanPref, FloatPref, IntPref,
                                       LongPref, StringPref, StringSetPref]}


class SharedPrefs(object):

  def __init__(self, device, package, filename):
    """Helper object to read and update "Shared Prefs" of Android apps.

    Such files typically look like, e.g.:

        <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
        <map>
          <int name="databaseVersion" value="107" />
          <boolean name="featureEnabled" value="false" />
          <string name="someHashValue">249b3e5af13d4db2</string>
        </map>

    Example usage:

        prefs = shared_prefs.SharedPrefs(device, 'com.my.app', 'my_prefs.xml')
        prefs.Load()
        prefs.GetString('someHashValue') # => '249b3e5af13d4db2'
        prefs.SetInt('databaseVersion', 42)
        prefs.Remove('featureEnabled')
        prefs.Commit()

    The object may also be used as a context manager to automatically load and
    commit, respectively, upon entering and leaving the context.

    Args:
      device: A DeviceUtils object.
      package: A string with the package name of the app that owns the shared
        preferences file.
      filename: A string with the name of the preferences file to read/write.
    """
    self._device = device
    self._xml = None
    self._package = package
    self._filename = filename
    self._path = '/data/data/%s/shared_prefs/%s' % (package, filename)
    self._changed = False

  def __repr__(self):
    """Get a useful printable representation of the object."""
    return '<{cls} file {filename} for {package} on {device}>'.format(
      cls=type(self).__name__, filename=self.filename, package=self.package,
      device=str(self._device))

  def __str__(self):
    """Get the underlying xml document as a string."""
    return _XML_DECLARATION + ElementTree.tostring(self.xml)

  @property
  def package(self):
    """Get the package name of the app that owns the shared preferences."""
    return self._package

  @property
  def filename(self):
    """Get the filename of the shared preferences file."""
    return self._filename

  @property
  def path(self):
    """Get the full path to the shared preferences file on the device."""
    return self._path

  @property
  def changed(self):
    """True if properties have changed and a commit would be needed."""
    return self._changed

  @property
  def xml(self):
    """Get the underlying xml document as an ElementTree object."""
    if self._xml is None:
      self._xml = ElementTree.Element('map')
    return self._xml

  def Load(self):
    """Load the shared preferences file from the device.

    A empty xml document, which may be modified and saved on |commit|, is
    created if the file does not already exist.
    """
    if self._device.FileExists(self.path):
      self._xml = ElementTree.fromstring(
          self._device.ReadFile(self.path, as_root=True))
      assert self._xml.tag == 'map'
    else:
      self._xml = None
    self._changed = False

  def Clear(self):
    """Clear all of the preferences contained in this object."""
    if self._xml is not None and len(self):  # only clear if not already empty
      self._xml = None
      self._changed = True

  def Commit(self):
    """Save the current set of preferences to the device.

    Only actually saves if some preferences have been modified.
    """
    if not self.changed:
      return
    self._device.RunShellCommand(
        ['mkdir', '-p', posixpath.dirname(self.path)],
        as_root=True, check_return=True)
    self._device.WriteFile(self.path, str(self), as_root=True)
    # Creating the directory/file can cause issues with SELinux if they did
    # not already exist. As a workaround, apply the package's security context
    # to the shared_prefs directory, which mimics the behavior of a file
    # created by the app itself
    if self._device.build_version_sdk >= version_codes.MARSHMALLOW:
      security_context = self._GetSecurityContext(self.package)
      if security_context == None:
        raise device_errors.CommandFailedError(
            'Failed to get security context for %s' % self.package)
      self._device.RunShellCommand(
          ['chcon', '-R', security_context,
           '/data/data/%s/shared_prefs' % self.package],
          as_root=True, check_return=True)
    self._device.KillAll(self.package, exact=True, as_root=True, quiet=True)
    self._changed = False

  def __len__(self):
    """Get the number of preferences in this collection."""
    return len(self.xml)

  def PropertyType(self, key):
    """Get the type (i.e. tag name) of a property in the collection."""
    return self._GetChild(key).tag

  def HasProperty(self, key):
    try:
      self._GetChild(key)
      return True
    except KeyError:
      return False

  def GetBoolean(self, key):
    """Get a boolean property."""
    return BooleanPref(self._GetChild(key)).get()

  def SetBoolean(self, key, value):
    """Set a boolean property."""
    self._SetPrefValue(key, value, BooleanPref)

  def GetFloat(self, key):
    """Get a float property."""
    return FloatPref(self._GetChild(key)).get()

  def SetFloat(self, key, value):
    """Set a float property."""
    self._SetPrefValue(key, value, FloatPref)

  def GetInt(self, key):
    """Get an int property."""
    return IntPref(self._GetChild(key)).get()

  def SetInt(self, key, value):
    """Set an int property."""
    self._SetPrefValue(key, value, IntPref)

  def GetLong(self, key):
    """Get a long property."""
    return LongPref(self._GetChild(key)).get()

  def SetLong(self, key, value):
    """Set a long property."""
    self._SetPrefValue(key, value, LongPref)

  def GetString(self, key):
    """Get a string property."""
    return StringPref(self._GetChild(key)).get()

  def SetString(self, key, value):
    """Set a string property."""
    self._SetPrefValue(key, value, StringPref)

  def GetStringSet(self, key):
    """Get a string set property."""
    return StringSetPref(self._GetChild(key)).get()

  def SetStringSet(self, key, value):
    """Set a string set property."""
    self._SetPrefValue(key, value, StringSetPref)

  def Remove(self, key):
    """Remove a preference from the collection."""
    self.xml.remove(self._GetChild(key))

  def AsDict(self):
    """Return the properties and their values as a dictionary."""
    d = {}
    for child in self.xml:
      pref = _PREF_TYPES[child.tag](child)
      d[child.get('name')] = pref.get()
    return d

  def __enter__(self):
    """Load preferences file from the device when entering a context."""
    self.Load()
    return self

  def __exit__(self, exc_type, _exc_value, _traceback):
    """Save preferences file to the device when leaving a context."""
    if not exc_type:
      self.Commit()

  def _GetChild(self, key):
    """Get the underlying xml node that holds the property of a given key.

    Raises:
      KeyError when the key is not found in the collection.
    """
    for child in self.xml:
      if child.get('name') == key:
        return child
    raise KeyError(key)

  def _SetPrefValue(self, key, value, pref_cls):
    """Set the value of a property.

    Args:
      key: The key of the property to set.
      value: The new value of the property.
      pref_cls: A subclass of BasePref used to access the property.

    Raises:
      TypeError when the key already exists but with a different type.
    """
    try:
      pref = pref_cls(self._GetChild(key))
      old_value = pref.get()
    except KeyError:
      pref = pref_cls(ElementTree.SubElement(
          self.xml, pref_cls.tag_name, {'name': key}))
      old_value = None
    if old_value != value:
      pref.set(value)
      self._changed = True
      logger.info('Setting property: %s', pref)

  def _GetSecurityContext(self, package):
    for line in self._device.RunShellCommand(['ls', '-Z', '/data/data/'],
                                             as_root=True, check_return=True):
      split_line = line.split()
      # ls -Z output differs between Android versions, but the package is
      # always last and the context always starts with "u:object"
      if split_line[-1] == package:
        for column in split_line:
          if column.startswith('u:object'):
            return column
    return None
