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

"""Utility functions for modifying an app's settings file using JSON."""

import json
import logging


def UnicodeToStr(data):
  """Recursively converts any Unicode to Python strings.

  Args:
    data: The data to be converted.

  Return:
    A copy of the given data, but with instances of Unicode converted to Python
    strings.
  """
  if isinstance(data, dict):
    return {
        UnicodeToStr(key): UnicodeToStr(value)
        for key, value in data.items()
    }
  if isinstance(data, list):
    return [UnicodeToStr(element) for element in data]
  try:
    # Python-2 compatibility.
    if isinstance(data, unicode):
      return data.encode('utf-8')
  except NameError:
    # Strings are already unicode in python3.
    pass
  return data


def ExtractSettingsFromJson(filepath):
  """Extracts the settings data from the given JSON file.

  Args:
    filepath: The path to the JSON file to read.

  Return:
    The data read from the JSON file with strings converted to Python strings.
  """
  # json.load() loads strings as unicode, which causes issues when trying
  # to edit string values in preference files, so convert to Python strings
  with open(filepath) as prefs_file:
    return UnicodeToStr(json.load(prefs_file))


def ApplySharedPreferenceSetting(shared_pref, setting):
  """Applies the given app settings to the given device.

  Modifies an installed app's settings by modifying its shared preference
  settings file. Provided settings data must be a settings dictionary,
  which are in the following format:
  {
    "package": "com.example.package",
    "filename": "AppSettingsFile.xml",
    "supports_encrypted_path": true,
    "set": {
      "SomeBoolToSet": true,
      "SomeStringToSet": "StringValue",
    },
    "remove": [
      "list",
      "of",
      "keys",
      "to",
      "remove",
    ]
  }

  Example JSON files that can be read with ExtractSettingsFromJson and passed to
  this function are in //chrome/android/shared_preference_files/test/.

  Args:
    shared_pref: The devil SharedPrefs object for the device the settings will
        be applied to.
    setting: A settings dictionary to apply.
  """
  shared_pref.Load()
  for key in setting.get('remove', []):
    try:
      shared_pref.Remove(key)
    except KeyError:
      logging.warning("Attempted to remove non-existent key %s", key)
  for key, value in setting.get('set', {}).items():
    is_set = False
    if not is_set and isinstance(value, bool):
      shared_pref.SetBoolean(key, value)
      is_set = True
    try:
      # Python-2 compatibility.
      if not is_set and isinstance(value, basestring):
        shared_pref.SetString(key, value)
        is_set = True
      if not is_set and isinstance(value, (long, int)):
        shared_pref.SetLong(key, value)
        is_set = True
    except NameError:
      if not is_set and isinstance(value, str):
        shared_pref.SetString(key, value)
        is_set = True
      if not is_set and isinstance(value, int):
        shared_pref.SetLong(key, value)
        is_set = True
    if not is_set and isinstance(value, list):
      shared_pref.SetStringSet(key, value)
      is_set = True
    if not is_set:
      raise ValueError("Given invalid value type %s for key %s" % (
          str(type(value)), key))
  shared_pref.Commit()
