# 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
import urllib2

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/v1/"
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': urllib2.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': urllib2.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 = urllib2.urlopen(url_request)
    except (urllib2.URLError, urllib2.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