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

import logging

import common
from autotest_lib.frontend.afe.json_rpc import proxy as rpc_proxy
from autotest_lib.server.hosts import host_info
from autotest_lib.server.cros.dynamic_suite import frontend_wrappers

class AfeStore(host_info.CachingHostInfoStore):
    """Directly interact with the (given) AFE for host information."""

    _RETRYING_AFE_TIMEOUT_MIN = 5
    _RETRYING_AFE_RETRY_DELAY_SEC = 10

    def __init__(self, hostname, afe=None):
        """
        @param hostname: The name of the host for which we want to track host
                information.
        @param afe: A frontend.AFE object to make RPC calls. Will create one
                internally if None.
        """
        super(AfeStore, self).__init__()
        self._hostname = hostname
        self._afe = afe
        if self._afe is None:
            self._afe = frontend_wrappers.RetryingAFE(
                    timeout_min=self._RETRYING_AFE_TIMEOUT_MIN,
                    delay_sec=self._RETRYING_AFE_RETRY_DELAY_SEC)


    def __str__(self):
        return '%s[%s]' % (type(self).__name__, self._hostname)


    def _refresh_impl(self):
        """Obtains HostInfo directly from the AFE."""
        try:
            hosts = self._afe.get_hosts(hostname=self._hostname)
        except rpc_proxy.JSONRPCException as e:
            raise host_info.StoreError(e)

        if not hosts:
            raise host_info.StoreError('No hosts founds with hostname: %s' %
                                       self._hostname)

        if len(hosts) > 1:
            logging.warning(
                    'Found %d hosts with the name %s. Picking the first one.',
                    len(hosts), self._hostname)
        host = hosts[0]
        return host_info.HostInfo(host.labels, host.attributes)


    def _commit_impl(self, new_info):
        """Commits HostInfo back to the AFE.

        @param new_info: The new HostInfo to commit.
        """
        # TODO(pprabhu) crbug.com/680322
        # This method has a potentially malignent race condition. We obtain a
        # copy of HostInfo from the AFE and then add/remove labels / attribtes
        # based on that. If another user tries to commit it's changes in
        # parallel, we'll end up with corrupted labels / attributes.
        old_info = self._refresh_impl()
        self._remove_labels_on_afe(
                list(set(old_info.labels) - set(new_info.labels)))
        self._add_labels_on_afe(
                list(set(new_info.labels) - set(old_info.labels)))
        self._update_attributes_on_afe(old_info.attributes, new_info.attributes)


    def _remove_labels_on_afe(self, labels):
        """Requests the AFE to remove the given labels.

        @param labels: Remove these.
        """
        if not labels:
            return

        logging.debug('removing labels: %s', labels)
        try:
            self._afe.run('host_remove_labels', id=self._hostname,
                          labels=labels)
        except rpc_proxy.JSONRPCException as e:
            raise host_info.StoreError(e)


    def _add_labels_on_afe(self, labels):
        """Requests the AFE to add the given labels.

        @param labels: Add these.
        """
        if not labels:
            return

        logging.info('adding labels: %s', labels)
        try:
            self._afe.run('host_add_labels', id=self._hostname, labels=labels)
        except rpc_proxy.JSONRPCException as e:
            raise host_info.StoreError(e)


    def _update_attributes_on_afe(self, old_attributes, new_attributes):
        """Updates host attributes on the afe to give dict.

        @param old_attributes: The current attributes on AFE.
        @param new_attributes: The new host attributes dict to set to.
        """
        left_only, right_only, differing = _dict_diff(old_attributes,
                                                      new_attributes)
        for key in left_only:
            self._afe.set_host_attribute(key, None, hostname=self._hostname)
        for key in right_only | differing:
            self._afe.set_host_attribute(key, new_attributes[key],
                                         hostname=self._hostname)


class AfeStoreKeepPool(AfeStore):
    """Interact with AFE for host information without deleting pool label."""

    def _adjust_pool(self, old_info, new_info):
        """Adjust pool labels when calculating the labels to remove/add.

        @param old_info: The HostInfo the host has previously, fetched from AFE.
        @param new_info: The HostInfo the host has after repair/provision.

        @returns: A tuple of list (labels_to_remove, labels_to_add).
        """
        labels_to_remove = list(set(old_info.labels) - set(new_info.labels))
        labels_to_add = list(set(new_info.labels) - set(old_info.labels))
        pool_to_remove = [l for l in labels_to_remove if 'pool:' in l]
        pool_to_add = [l for l in labels_to_add if 'pool:' in l]
        if pool_to_remove and not pool_to_add:
            labels_to_remove = list(set(labels_to_remove) - set(pool_to_remove))

        return labels_to_remove, labels_to_add

    def _commit_impl(self, new_info):
        """Commits HostInfo back to the AFE.

        @param new_info: The new HostInfo to commit.

        It won't delete pool label if no pool label will be added later.
        """
        # TODO(pprabhu) crbug.com/680322
        # This method has a potentially malignent race condition. We obtain a
        # copy of HostInfo from the AFE and then add/remove labels / attribtes
        # based on that. If another user tries to commit it's changes in
        # parallel, we'll end up with corrupted labels / attributes.
        old_info = self._refresh_impl()
        labels_to_remove, labels_to_add = self._adjust_pool(old_info, new_info)
        self._remove_labels_on_afe(labels_to_remove)
        self._add_labels_on_afe(labels_to_add)
        self._update_attributes_on_afe(old_info.attributes, new_info.attributes)


def _dict_diff(left_dict, right_dict):
    """Return the keys where the given dictionaries differ.

    This function assumes that the values in the dictionary support checking for
    equality.

    @param left_dict: The "left" dictionary in the diff.
    @param right_dict: The "right" dictionary in the diff.
    @returns: A 3-tuple (left_only, right_only, differing) of keys where
            left_only contains the keys that exist in left_dict only, right_only
            contains keys that exist in right_dict only and differing contains
            keys that exist in both, but where values differ.
    """
    left_keys = set(left_dict)
    right_keys = set(right_dict)
    differing_keys = {key for key in left_keys & right_keys
                      if left_dict[key] != right_dict[key]}
    return left_keys - right_keys, right_keys - left_keys, differing_keys
