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

import logging
import re
import time

from autotest_lib.client.bin import utils
from autotest_lib.server.cros.servo import chrome_ec


class PDTesterError(Exception):
    """Error object for PDTester"""
    pass


class PDTester(chrome_ec.ChromeEC):
    """Manages control of a PDTester hardware.

    PDTester is a general term for hardware developed to aid in USB type-C
    debug and control of various type C host devices. It can be either a
    Plankton board or a Servo v4 board.

    We control the PDTester board via the UART and the Servod interfaces.
    PDTester provides many interfaces that access the hardware. It can
    also be passed into the PDConsoleUtils as a console which then
    provides methods to access the pd console.

    This class is to abstract these interfaces.
    """
    # USB charging command delays in seconds.
    USBC_COMMAND_DELAY = 0.5
    # PDTester USBC commands.
    USBC_ROLE= 'usbc_role' # TODO(b:140256624): deprecate by USBC_PR
    USBC_PR= 'usbc_pr'
    USBC_MUX = 'usbc_mux'
    RE_USBC_ROLE_VOLTAGE = r'src(\d+)v'
    USBC_SRC_CAPS = 'ada_srccaps'
    USBC_CHARGING_VOLTAGES = {
        0: 'sink',
        5: 'src5v',
        9: 'src9v',
        10: 'src10v',
        12: 'src12v',
        15: 'src15v',
        20: 'src20v'}
    # TODO(b:140256624): deprecate by USBC_CHARGING_VOLTAGES
    USBC_CHARGING_VOLTAGES_LEGACY = {
        0: 'sink',
        5: 'src5v',
        12: 'src12v',
        20: 'src20v'}
    USBC_MAX_VOLTAGE = 20
    VBUS_VOLTAGE_MV = 'vbus_voltage'
    VBUS_CURRENT_MA = 'vbus_current'
    VBUS_POWER_MW = 'vbus_power'
    # USBC PD states.
    USBC_PD_STATES = {
        'sink': 'SNK_READY',
        'source': 'SRC_READY'}
    POLL_STATE_SECS = 2

    def __init__(self, servo, servod_proxy):
        """Initialize and keep the servo object.

        @param servo: A Servo object
        @param servod_proxy: Servod proxy for pdtester host
        """
        self.servo_type = servo.get_servo_version()
        if 'servo_v4' in self.servo_type:
            uart_prefix = 'servo_v4_uart'
        else:
            uart_prefix = 'ec_uart'

        super(PDTester, self).__init__(servo, uart_prefix)
        # save servod proxy for methods that access PDTester servod
        self._server = servod_proxy
        self.init_hardware()


    def init_hardware(self):
        """Initializes PDTester hardware."""
        if self.servo_type == 'plankton':
            if not int(self.get('debug_usb_sel')):
                raise PDTesterError('debug_usb_sel (SW3) should be ON!! '
                                    'Please use CN15 to connect Plankton.')
            self.set('typec_to_hub_sw', '0')
            self.set('usb2_mux_sw', '1')
            self.set('usb_dn_pwren', 'on')


    def set(self, control_name, value):
        """Sets the value of a control using servod.

        @param control_name: pdtester servo control item
        @param value: value to set pdtester servo control item
        """
        assert control_name
        self._server.set(control_name, value)


    def get(self, control_name):
        """Gets the value of a control from servod.

        @param control_name: pdtester servo control item
        """
        assert control_name
        return self._server.get(control_name)


    @property
    def vbus_voltage(self):
        """Gets PDTester VBUS voltage in volts."""
        return float(self.get(self.VBUS_VOLTAGE_MV)) / 1000.0


    @property
    def vbus_current(self):
        """Gets PDTester VBUS current in amps."""
        return float(self.get(self.VBUS_CURRENT_MA)) / 1000.0


    @property
    def vbus_power(self):
        """Gets PDTester charging power in watts."""
        return float(self.get(self.VBUS_POWER_MW)) / 1000.0

    def get_adapter_source_caps(self):
        """Gets a list of SourceCap Tuples in mV/mA."""
        try:
            res = self.get(self.USBC_SRC_CAPS)
        except:
            raise PDTesterError('Unsupported servov4 command(%s). '
                                'Maybe firmware or servod too old? '
                                'sudo servo_updater -b servo_v4; '
                                'sudo emerge hdctools' % self.USBC_SRC_CAPS)

        srccaps = []
        for pdo_str in res:
            m = re.match(r'\d: (\d+)mV/(\d+)mA', pdo_str)
            srccaps.append((int(m.group(1)), int(m.group(2))))
        return srccaps

    def get_charging_voltages(self):
        """Gets the lists of available charging voltages of the adapter."""
        try:
            srccaps = self.get_adapter_source_caps()
        except PDTesterError:
            # htctools and servov4 is not updated, fallback to the old path.
            logging.warn('hdctools or servov4 firmware too old, fallback to '
                         'fixed charging voltages.')
            return self.USBC_CHARGING_VOLTAGES_LEGACY.keys()

        # insert 0 voltage for sink
        vols = [0]
        for pdo in srccaps:
            vols.append(pdo[0]/1000)
        return vols

    def charge(self, voltage):
        """Sets PDTester to provide power at specific voltage.

        @param voltage: Specified charging voltage in volts.
        """
        charging_voltages = self.get_charging_voltages()
        if voltage not in charging_voltages:
            logging.warning('Unsupported voltage(%s) of the adapter. '
                            'Maybe firmware or servod too old? '
                            'sudo servo_updater -b servo_v4; '
                            'sudo emerge hdctools' % voltage)

        try:
            self.set(self.USBC_PR, self.USBC_CHARGING_VOLTAGES[voltage])
        except:
            self.set(self.USBC_ROLE,
                     self.USBC_CHARGING_VOLTAGES_LEGACY[voltage])
        time.sleep(self.USBC_COMMAND_DELAY)

    @property
    def charging_voltage(self):
        """Gets current charging voltage."""
        try:
            usbc_pr = self.get(self.USBC_PR)
        except:
            logging.warn('Unsupported control(%s). '
                         'Maybe firmware or servod too old? '
                         'sudo servo_updater -b servo_v4; '
                         'sudo emerge hdctools' % self.USBC_PR)
            usbc_pr = self.get(self.USBC_ROLE)
        m = re.match(self.RE_USBC_ROLE_VOLTAGE, usbc_pr)
        if m:
            return int(m.group(1))

        if usbc_pr == self.USBC_CHARGING_VOLTAGES[0]:
            return 0

        raise PDTesterError('Invalid USBC power role: %s' % usbc_pr)


    def poll_pd_state(self, state):
        """Polls until PDTester pd goes to the specific state.

        @param state: Specified pd state name.
        """
        if state not in self.USBC_PD_STATES:
            raise PDTesterError('Invalid state name: %s' % state)
        utils.poll_for_condition(
            lambda: self.get('pd_state') == self.USBC_PD_STATES[state],
            exception=utils.TimeoutError('PDTester not in %s state '
                                         'after %s seconds.' %
                                         (self.USBC_PD_STATES[state],
                                          self.POLL_STATE_SECS)),
            timeout=self.POLL_STATE_SECS)


    def set_usbc_mux(self, mux):
        """Sets PDTester usbc_mux.

        @param mux: Specified mux state name.
        """
        if mux not in ['dp', 'usb']:
            raise PDTesterError('Invalid mux name: %s, '
                                'should be either \'dp\' or \'usb\'.' % mux)
        self.set(self.USBC_MUX, mux)
        time.sleep(self.USBC_COMMAND_DELAY)
