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

"""Compass test which requires operator place the DUT heading north and south.
"""


import math
import time
import unittest

import factory_common  # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.test import factory
from cros.factory.test.i18n import _
from cros.factory.test.i18n import test_ui as i18n_test_ui
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
from cros.factory.utils import type_utils

_COMPASS_CSS = """
.compass {
  width: 10em;
  height: 10em;
  border: 2px solid black;
  border-radius: 50%;
  font-size: 2em;
  text-align: center;
  margin: 0.5em;
}

.success {
  background: #afa;
  font-size: 4em;
}

#state {
  flex-flow: row;
}
"""

_STATE_TEMPLATE = """
<div>
  in_magn_x: {in_magn_x}<br>
  in_magn_y: {in_magn_y}<br>
  in_magn_z: {in_magn_z}<br>
  degree: {degree:.1f}<br>
</div>
<div class='compass' style='transform: rotate({degree}deg)'>
  <div style='color: red'>N</div>
  <div style='position: absolute; bottom: 0; left: 0; right: 0'>S</div>
</div>
"""

_MSG_STATUS_SUCCESS = i18n_test_ui.MakeI18nLabel('Success!')
_HTML_STATUS_SUCCESS = '<div class="success">%s</div>' % _MSG_STATUS_SUCCESS

_NORTH = (0, 1)
_SOUTH = (0, -1)

_FLASH_STATUS_TIME = 1


class CompassTest(unittest.TestCase):
  ARGS = [
      Arg('tolerance', int, 'The tolerance in degree.',
          default=5, optional=True),
      Arg('location', type_utils.Enum(['base', 'lid']),
          'Where the compass is located.',
          default='base', optional=True)
  ]

  def setUp(self):
    self.dut = device_utils.CreateDUTInterface()
    self.controller = self.dut.magnetometer.GetController(
        location=self.args.location)
    self.ui = test_ui.UI()
    self.ui.AppendCSS(_COMPASS_CSS)
    self._template = ui_templates.TwoSections(self.ui)

  def runTest(self):
    self._SetInstruction(_('north'))
    sync_utils.PollForCondition(
        poll_method=lambda: self._CheckDirection(_NORTH),
        timeout_secs=1000,
        poll_interval_secs=0.1)
    self._template.SetState(_HTML_STATUS_SUCCESS)
    time.sleep(_FLASH_STATUS_TIME)

    self._SetInstruction(_('south'))
    sync_utils.PollForCondition(
        poll_method=lambda: self._CheckDirection(_SOUTH),
        timeout_secs=1000,
        poll_interval_secs=0.1)
    self._template.SetState(_HTML_STATUS_SUCCESS)
    time.sleep(_FLASH_STATUS_TIME)

  def _SetInstruction(self, direction):
    label = i18n_test_ui.MakeI18nLabel(
        'Put the DUT towards {direction}', direction=direction)
    self._template.SetTitle(label)

  def _CalculateDirection(self, x, y):
    """Calculate the absolute direction of the compass in degree.

    Args:
      x: X-axis component of the direction. X-axis points towards east.
      y: Y-axis component of the direction. Y-axis points towards north.

    Returns:
      Directed angle relative to north (0, 1), in degree, clockwise.
      For example:
          North = 0
          East = 90
          South = 180 = -180
          West = -90
    """
    rad = math.atan2(x, y)
    return rad / math.pi * 180

  def _CalculateAngle(self, x1, y1, x2, y2):
    """Calculate the angle between two vectors (x1, y1) and (x2, y2)."""
    rad = math.acos(
        (x1 * x2 + y1 * y2) / math.hypot(x1, y1) / math.hypot(x2, y2))
    return rad / math.pi * 180

  def _CheckDirection(self, expected_direction):
    values = self.controller.GetData(capture_count=1)
    x, y = values['in_magn_x'], values['in_magn_y']
    if x == 0 and y == 0:
      # atan2(0, 0) returns 0, we need to avoid this case.
      raise factory.FactoryTestFailure(
          'Sensor outputs (0, 0), possibly not working.')
    degree = self._CalculateDirection(x, y)
    self._template.SetState(_STATE_TEMPLATE.format(degree=degree, **values))
    return (
        self._CalculateAngle(x, y, *expected_direction) < self.args.tolerance)
