# Lint as: python2, python3
# Copyright 2016 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 json
import logging
from six.moves import urllib

from autotest_lib.client.common_lib import global_config

# HWID info types to request.
HWID_INFO_LABEL = 'dutlabel'
HWID_INFO_BOM = 'bom'
HWID_INFO_SKU = 'sku'
HWID_INFO_TYPES = [HWID_INFO_BOM, HWID_INFO_SKU, HWID_INFO_LABEL]

# HWID url vars.
HWID_VERSION = 'v1'
HWID_BASE_URL = 'https://www.googleapis.com/chromeoshwid'
CHROMEOS_HWID_SERVER_URL = "https://chromeos-hwid.appspot.com/api/chromeoshwid"
URL_FORMAT_STRING='%(base_url)s/%(version)s/%(info_type)s/%(hwid)s/?key=%(key)s'

# Key file name to use when we don't want hwid labels.
KEY_FILENAME_NO_HWID = 'no_hwid_labels'

class HwIdException(Exception):
    """Raised whenever anything fails in the hwid info request."""


def get_hwid_info(hwid, info_type, key_file):
    """Given a hwid and info type, return a dict of the requested info.

    @param hwid: hwid to use for the query.
    @param info_type: String of info type requested.
    @param key_file: Filename that holds the key for authentication.

    @return: A dict of the info.

    @raises HwIdException: If hwid/info_type/key_file is invalid or there's an
                           error anywhere related to getting the raw hwid info
                           or decoding it.
    """
    # There are situations we don't want to call out to the hwid service, we use
    # the key_file name as the indicator for that.
    if key_file == KEY_FILENAME_NO_HWID:
        return {}

    if not isinstance(hwid, str):
        raise ValueError('hwid is not a string.')

    if info_type not in HWID_INFO_TYPES:
        raise ValueError('invalid info type: "%s".' % info_type)

    hwid_info_dict = _try_hwid_v1(hwid, info_type)
    if hwid_info_dict is not None:
        return hwid_info_dict
    else:
        logging.debug("Switch back to use old endpoint")

    key = None
    with open(key_file) as f:
        key = f.read().strip()

    url_format_dict = {'base_url': HWID_BASE_URL,
                       'version': HWID_VERSION,
                       'info_type': info_type,
                       'hwid': urllib.parse.quote(hwid),
                       'key': key}
    return _fetch_hwid_response(url_format_dict)


def get_all_possible_dut_labels(key_file):
    """Return all possible labels that can be supplied by dutlabels.

    We can send a dummy key to the service to retrieve all the possible
    labels the service will provide under the dutlabel api call.  We need
    this in order to track which labels we can remove if they're not detected
    on a dut anymore.

    @param key_file: Filename that holds the key for authentication.

    @return: A list of all possible labels.
    """
    return get_hwid_info('dummy_hwid', HWID_INFO_LABEL, key_file).get(
            'possible_labels', [])


def _try_hwid_v1(hwid, info_type):
    """Try chromeos-hwid endpoints for fetching hwid info.

    @param hwid: a string hardware ID.
    @param info_type: String of info type requested.

    @return a dict of hwid info.
    """
    key_file_path = global_config.global_config.get_config_value(
            'CROS', 'NEW_HWID_KEY', type=str, default="")
    if key_file_path == "":
        return None

    key = None
    with open(key_file_path) as f:
        key = f.read().strip()

    if key is None:
        return None

    url_format_dict = {'base_url': CHROMEOS_HWID_SERVER_URL,
                       'version': HWID_VERSION,
                       'info_type': info_type,
                       'hwid': urllib.parse.quote(hwid),
                       'key': key}

    try:
        return _fetch_hwid_response(url_format_dict)
    except Exception as e:
        logging.debug("fail to call new HWID endpoint: %s", str(e))
        return None


def _fetch_hwid_response(req_parameter_dict):
    """Fetch and parse hwid response.

    @param req_parameter_dict: A dict of url parameters.

    @return a dict of hwid info.
    """
    url_request = URL_FORMAT_STRING % req_parameter_dict
    try:
        page_contents = urllib.request.urlopen(url_request)
    except (urllib.error.URLError, urllib.error.HTTPError) as e:
        # TODO(kevcheng): Might need to scrub out key from exception message.
        raise HwIdException('error retrieving raw hwid info: %s' % e)

    try:
        hwid_info_dict = json.load(page_contents)
    except ValueError as e:
        raise HwIdException('error decoding hwid info: %s - "%s"' %
                            (e, page_contents.getvalue()))
    finally:
        page_contents.close()

    return hwid_info_dict
