# Copyright 2017 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.


"""Updates Device Data (manually or from predefined values in test list).

Description
-----------
The Device Data (``cros.factory.test.device_data``) is a special data structure
for manipulating DUT information.  This test can determine Device Data
information (usually for VPD) without using shopfloor backend, usually
including:

- ``serials.serial_number``: The device serial number.
- ``vpd.ro.region``: Region data (RO region).
- ``vpd.rw.ubind_attribute`` and ``vpd.rw.gbind_attribute``: User and group
  registration codes.
- Or other values specified in argument ``fields`` or ``config_name``.

When argument `manual_input` is True, every values specified in ``fields`` will
be displayed on screen with an edit box before written into device data.
Note all the values will be written as string in manual mode.

The ``fields`` argument is a sequence in format
``(data_key, value, display_name, value_check)``:

================ ==============================================================
Name             Description
================ ==============================================================
``data_key``     The Device Data key name to write.
``value``        The value to be written, can be modified if ``manual_input`` is
                 True.
``display_name`` The label or name to be displayed on UI.
``value_check``  To validate the input value. Can be a regular expression,
                 sequence of string or boolean values, or None for any string.
================ ==============================================================

If you want to manually configure without default values, the sequence can be
replaced by a simple string of key name.

The ``config_name`` refers to a JSON config file loaded by
``cros.factory.py.utils.config_utils`` with single dictionary that the keys
and values will be directly sent to Device Data. This is helpful if you need to
define board-specific data.

``config_name`` and ``fields`` are both optional, but you must specify at least
one.

If you want to set device data (especially VPD values) using shopfloor or
pre-defined values:

1. Use ``shopfloor_service`` test with method=GetDeviceInfo to retrieve
   ``vpd.{ro,rw}.*``.
2. Use ``update_device_data`` test to write pre-defined or update values to
   ``vpd.{ro,rw}.*``.
3. Use ``write_device_data_to_vpd`` to flush data into firmware VPD sections.

Test Procedure
--------------
If argument ``manual_input`` is not True, this will be an automated test
without user interaction.

If argument ``manual_input`` is True, the test will go through all the fields:

1. Display the name and key of the value.
2. Display an input edit box for simple values, or a list of selection
   if the ``value_check`` is a sequence of strings or boolean values.
3. Wait for operator to select or input right value.
4. If operator presses ESC, abandon changes and keep original value.
5. If operator clicks Enter, validate the input by ``value_check`` argument.
   If failed, prompt and go back to 3.
   Otherwise, write into device data and move to next field.
6. Pass when all fields were processed.

Dependency
----------
None. This test only deals with the ``device_data`` module inside factory
software framework.

Examples
--------
To silently load device-specific data defined in board overlay
``py/config/default_device_data.json``, add this in test list::

  {
    "pytest_name": "update_device_data",
    "args": {
      "config_name": "default",
      "manual_input": false
    }
  }

To silently set a device data 'component.has_touchscreen' to True::

  {
    "pytest_name": "update_device_data",
    "args": {
      "fields": [
        [
          "component.has_touchscreen",
          true,
          "Device has touch screen",
          null
        ]
      ],
      "manual_input": false
    }
  }

For RMA process to set serial number, region, registration codes, and specify
if the device has peripherals like touchscreen::

  {
    "pytest_name": "update_device_data",
    "args": {
      "fields": [
        [
          "serials.serial_number",
          null,
          "Device Serial Number",
          "[A-Z0-9]+"
        ],
        ["vpd.ro.region", "us", "Region", null],
        ["vpd.rw.ubind_attribute", null, "User ECHO", null],
        ["vpd.rw.gbind_attribute", null, "Group ECHO", null],
        [
          "component.has_touchscreen",
          null,
          "Has touchscreen",
          [true, false]
        ]
      ]
    }
  }

If you don't need default values, there's an alternative to list only key
names::

  {
    "pytest_name": "update_device_data",
    "args": {
      "fields": [
        "serials.serial_number",
        "vpd.ro.region",
        "vpd.rw.ubind_attribute",
        "vpd.rw.gbind_attribute"
      ]
    }
  }
"""


from __future__ import print_function

import Queue
import logging
import re

import factory_common  # pylint: disable=unused-import
from cros.factory.test import device_data
from cros.factory.test import i18n
from cros.factory.test.i18n import _
from cros.factory.test.l10n import regions
from cros.factory.test import test_case
from cros.factory.test import test_ui
from cros.factory.test import ui_templates
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import sync_utils


# Known regions to be listed first.
_KNOWN_REGIONS = (
    'us', 'gb', 'de', 'fr', 'ch', 'nordic', 'latam-es-419',
)

_KNOWN_KEY_LABELS = {
    device_data.KEY_SERIAL_NUMBER: _('Device Serial Number'),
    device_data.KEY_MLB_SERIAL_NUMBER: _('Mainboard Serial Number'),
    device_data.KEY_VPD_REGION: _('VPD Region Code'),
    device_data.KEY_VPD_USER_REGCODE: _('User Registration Code'),
    device_data.KEY_VPD_GROUP_REGCODE: _('Group Registration Code'),
}

_SELECTION_PER_PAGE = 10


class DataEntry(object):
  """Quick access to an entry in DeviceData.

  Properties:
    key: A string as Device Data key.
    value: Default value to be set.
    label: A I18N label to display on UI.
    value_check: A regular expression string or list of values or None for
      validation of new value.
    re_checker: The compiled regular expression to validate input value.
    codes: A list of string for UI to use as reference to selected values.
    options: A list of strings for UI to display as option to select from.
  """

  def __init__(self, key, value=None, display_name=None, value_check=None):
    device_data.CheckValidDeviceDataKey(key)
    self.key = key
    self.value = device_data.GetDeviceData(key) if value is None else value
    if display_name is None and key in _KNOWN_KEY_LABELS:
      display_name = _KNOWN_KEY_LABELS[key]
    self.label = (i18n.StringFormat('{name} ({key})', name=display_name,
                                    key=key) if display_name else key)

    self.re_checker = None
    self.value_check = None
    self.codes = None
    self.options = None

    if isinstance(value, bool) and value_check is None:
      value_check = [True, False]

    if isinstance(value_check, basestring):
      self.re_checker = re.compile(value_check)
    elif isinstance(value_check, list):
      self.value_check = value_check
      self.codes = [str(v) for v in value_check]
    elif value_check is None:
      self.value_check = value_check
    else:
      raise TypeError('value_check (%r) for %s must be either regex, sequence, '
                      'or None.' % (value_check, key))

    # Region should be processed differently.
    if key == device_data.KEY_VPD_REGION:
      all_regions = regions.REGIONS.keys()
      if not value_check:
        ordered_values = [v for v in _KNOWN_REGIONS if v in all_regions]
        other_values = sorted(set(all_regions) - set(ordered_values))
        value_check = ordered_values + other_values
        self.value_check = value_check

      assert set(self.value_check).issubset(set(all_regions))
      self.codes = value_check
      self.options = [
          '%d - %s; %s' % (i + 1, v, regions.REGIONS[v].description)
          for i, v in enumerate(self.codes)]
    elif isinstance(self.value_check, list):
      self.codes = [str(v) for v in self.value_check]
      self.options = [
          '%d - %s' % (i + 1, v) if isinstance(v, basestring) else str(v)
          for i, v in enumerate(self.value_check)]

  def GetInputList(self):
    """Returns the list of allowed input, or None for raw input."""
    return self.codes

  def GetOptionList(self):
    """Returns the options to display if the allowed input is a list."""
    return self.options

  def GetValueIndex(self):
    """Returns the index of current value in input list.

    Raises:
      ValueError if current value is not in known list.
    """
    return self.value_check.index(self.value)

  def IsValidInput(self, input_data):
    """Checks if input data is valid.

    The input data may be a real string or one of the value in self.codes.
    """
    if self.re_checker:
      logging.info('trying re_checker')
      return self.re_checker.match(input_data)
    if self.value_check is None:
      return True
    if self.codes:
      return input_data in self.codes
    raise ValueError('Unknown value_check: %r' % self.value_check)

  def GetValue(self, input_data):
    """Returns the real value from input data."""
    if self.codes:
      return self.value_check[self.codes.index(input_data)]
    return input_data


class UpdateDeviceData(test_case.TestCase):
  ARGS = [
      Arg('manual_input', bool,
          'Set to False to silently updating all values. Otherwise each value '
          'will be prompted before set into Device Data.',
          default=True),
      Arg('config_name', basestring,
          'A JSON config name to load representing the device data to update.',
          default=None),
      Arg('fields', list,
          ('A list of [data_key, value, display_name, value_check] '
           'indicating the Device Data field by data_key must be updated to '
           'specified value.'),
          default=None),
  ]

  def setUp(self):
    # Either config_name or fields must be specified.
    if self.args.config_name is None and self.args.fields is None:
      raise ValueError('Either config_name or fields must be specified.')

    fields = []

    if self.args.config_name:
      fields += [(k, v, None, None) for k, v in
                 device_data.LoadConfig(self.args.config_name).iteritems()]

    if self.args.fields:
      fields += self.args.fields

    # Syntax sugar: If the sequence was replaced by a simple string, consider
    # that as data_key only.
    self.entries = [
        DataEntry(args) if isinstance(args, basestring) else DataEntry(*args)
        for args in fields
    ]

    # Setup UI and update accordingly.
    self.ui.ToggleTemplateClass('font-large', True)

  def runTest(self):
    if self.args.manual_input:
      for entry in self.entries:
        self.ManualInput(entry)
    else:
      results = dict((entry.key, entry.value) for entry in self.entries)
      device_data.UpdateDeviceData(results)

  def ManualInput(self, entry):
    event_subtype = 'devicedata-' + entry.key
    event_queue = Queue.Queue()

    if entry.GetInputList():
      self._RenderSelectBox(entry)
      self.ui.BindKeyJS(test_ui.ENTER_KEY, 'window.sendSelectValue(%r, %r)' %
                        (entry.key, event_subtype))
    else:
      self._RenderInputBox(entry)
      self.ui.BindKey(
          test_ui.ESCAPE_KEY, lambda unused_event: event_queue.put(None))
      self.ui.BindKeyJS(test_ui.ENTER_KEY, 'window.sendInputValue(%r, %r)' % (
          entry.key, event_subtype))

    self.event_loop.AddEventHandler(event_subtype, event_queue.put)

    while True:
      event = sync_utils.QueueGet(event_queue)
      if event is None:
        # ESC pressed.
        if entry.value is not None:
          break
        self._SetErrorMsg(
            _('No valid data on machine for {label}.', label=entry.label))
      else:
        data = event.data
        if entry.IsValidInput(data):
          value = entry.GetValue(data)
          if value is not None:
            device_data.UpdateDeviceData({entry.key: value})
          break
        self._SetErrorMsg(_('Invalid value for {label}.', label=entry.label))

    self.ui.UnbindAllKeys()
    self.event_loop.ClearHandlers()

  def _SetErrorMsg(self, msg):
    self.ui.SetHTML(
        ['<span class="test-error">', msg, '</span>'], id='errormsg')

  def _RenderSelectBox(self, entry):
    # Renders a select box to list all the possible values.
    select_box = ui_templates.SelectBox(entry.key, _SELECTION_PER_PAGE)
    for value, option in zip(entry.GetInputList(),
                             entry.GetOptionList()):
      select_box.AppendOption(value, option)

    try:
      select_box.SetSelectedIndex(entry.GetValueIndex())
    except ValueError:
      pass

    html = [
        _('Select {label}:', label=entry.label),
        select_box.GenerateHTML(),
        _('Select with ENTER')
    ]

    self.ui.SetState(html)
    self.ui.SetFocus(entry.key)

  def _RenderInputBox(self, entry):
    html = [
        _('Enter {label}: ', label=entry.label),
        '<input type="text" id="%s" value="%s" style="width: 20em;">'
        '<div id="errormsg" class="test-error"></div>' % (entry.key,
                                                          entry.value or '')
    ]

    if entry.value:
      # The "ESC" is available primarily for RMA and testing process, when
      # operator does not want to change existing serial number.
      html.append(_('(ESC to keep current value)'))

    self.ui.SetState(html)
    self.ui.SetSelected(entry.key)
    self.ui.SetFocus(entry.key)
