# Copyright (c) 2013 The Chromium 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 random

from time import sleep

import common
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.server.cros.ap_configurators import \
    ap_configurator_factory
from autotest_lib.client.common_lib.cros.network import ap_constants
from autotest_lib.server.cros.ap_configurators import ap_cartridge

# Max number of retry attempts to lock an ap.
MAX_RETRIES = 3


class ApLocker(object):
    """Object to keep track of AP lock state.

    @attribute configurator: an APConfigurator object.
    @attribute to_be_locked: a boolean, True iff ap has not been locked.
    @attribute retries: an integer, max number of retry attempts to lock ap.
    """


    def __init__(self, configurator, retries):
        """Initialize.

        @param configurator: an APConfigurator object.
        @param retries: an integer, max number of retry attempts to lock ap.
        """
        self.configurator = configurator
        self.to_be_locked = True
        self.retries = retries


    def __repr__(self):
        """@return class name, ap host name, lock status and retries."""
        return 'class: %s, host name: %s, to_be_locked = %s, retries = %d' % (
                self.__class__.__name__,
                self.configurator.host_name,
                self.to_be_locked,
                self.retries)


def construct_ap_lockers(ap_spec, retries, hostname_matching_only=False,
                         ap_test_type=ap_constants.AP_TEST_TYPE_CHAOS):
    """Convert APConfigurator objects to ApLocker objects for locking.

    @param ap_spec: an APSpec object
    @param retries: an integer, max number of retry attempts to lock ap.
    @param hostname_matching_only: a boolean, if True matching against
                                   all other APSpec parameters is not
                                   performed.
    @param ap_test_type: Used to determine which type of test we're
                         currently running (Chaos vs Clique).

    @return a list of ApLocker objects.
    """
    ap_lockers_list = []
    factory = ap_configurator_factory.APConfiguratorFactory(ap_test_type,
                                                            ap_spec)
    if hostname_matching_only:
        for ap in factory.get_aps_by_hostnames(ap_spec.hostnames):
            ap_lockers_list.append(ApLocker(ap, retries))
    else:
        for ap in factory.get_ap_configurators_by_spec(ap_spec):
            ap_lockers_list.append(ApLocker(ap, retries))

    if not len(ap_lockers_list):
        logging.error('Found no matching APs to test against for %s', ap_spec)

    logging.debug('Found %d APs', len(ap_lockers_list))
    return ap_lockers_list


class ApBatchLocker(object):
    """Object to lock/unlock an APConfigurator.

    @attribute SECONDS_TO_SLEEP: an integer, number of seconds to sleep between
                                 retries.
    @attribute ap_spec: an APSpec object
    @attribute retries: an integer, max number of retry attempts to lock ap.
                        Defaults to MAX_RETRIES.
    @attribute aps_to_lock: a list of ApLocker objects.
    @attribute manager: a HostLockManager object, used to lock/unlock APs.
    """


    MIN_SECONDS_TO_SLEEP = 10
    MAX_SECONDS_TO_SLEEP = 20


    def __init__(self, lock_manager, ap_spec, retries=MAX_RETRIES,
                 hostname_matching_only=False,
                 ap_test_type=ap_constants.AP_TEST_TYPE_CHAOS):
        """Initialize.

        @param ap_spec: an APSpec object
        @param retries: an integer, max number of retry attempts to lock ap.
                        Defaults to MAX_RETRIES.
        @param hostname_matching_only : a boolean, if True matching against
                                        all other APSpec parameters is not
                                        performed.
        @param ap_test_type: Used to determine which type of test we're
                             currently running (Chaos vs Clique).
        """
        self.aps_to_lock = construct_ap_lockers(ap_spec, retries,
                           hostname_matching_only=hostname_matching_only,
                           ap_test_type=ap_test_type)
        self.manager = lock_manager
        self._locked_aps = []


    def has_more_aps(self):
        """@return True iff there is at least one AP to be locked."""
        return len(self.aps_to_lock) > 0


    def lock_ap(self, ap_locker):
        """Locks an AP host in DataStore.

        @param ap_locker: an ApLocker object, AP to be locked.
        @return a boolean, True if ap_locker is locked.
        """

        if self.manager.lock([ap_locker.configurator.host_name]):
            self._locked_aps.append(ap_locker)
            logging.info('locked %s', ap_locker.configurator.host_name)
            ap_locker.to_be_locked = False
            return True
        else:
            ap_locker.retries -= 1
            logging.info('%d retries left for %s',
                         ap_locker.retries,
                         ap_locker.configurator.host_name)
            if ap_locker.retries == 0:
                logging.info('No more retries left. Remove %s from list',
                             ap_locker.configurator.host_name)
                ap_locker.to_be_locked = False

        return False



    def get_ap_batch(self, batch_size=ap_cartridge.THREAD_MAX):
        """Allocates a batch of locked APs.

        @param batch_size: an integer, max. number of aps to lock in one batch.
                           Defaults to THREAD_MAX in ap_cartridge.py
        @return a list of APConfigurator objects, locked in datastore.
        """
        # We need this while loop to continuously loop over the for loop.
        # To exit the while loop, we either:
        #  - locked batch_size number of aps and return them
        #  - exhausted all retries on all aps in aps_to_lock
        while len(self.aps_to_lock):
            ap_batch = []

            for ap_locker in self.aps_to_lock:
                logging.info('checking %s', ap_locker.configurator.host_name)
                # Lock AP in DataStore
                if self.lock_ap(ap_locker):
                    ap_batch.append(ap_locker.configurator)
                    if len(ap_batch) == batch_size:
                        break

            # Remove locked APs from list of APs to process.
            aps_to_rm = [ap for ap in self.aps_to_lock if not ap.to_be_locked]
            self.aps_to_lock = list(set(self.aps_to_lock) - set(aps_to_rm))
            for ap in aps_to_rm:
                logging.info('Removed %s from self.aps_to_lock',
                             ap.configurator.host_name)
            logging.info('Remaining aps to lock = %s',
                         [ap.configurator.host_name for ap in self.aps_to_lock])

            # Return available APs and retry remaining ones later.
            if ap_batch:
                return ap_batch

            # Sleep before next retry.
            if self.aps_to_lock:
                seconds_to_sleep = random.randint(self.MIN_SECONDS_TO_SLEEP,
                                                  self.MAX_SECONDS_TO_SLEEP)
                logging.info('Sleep %d sec before retry', seconds_to_sleep)
                sleep(seconds_to_sleep)

        return []


    def unlock_one_ap(self, host_name):
        """
        Unlock one AP from datastore after we're done.

        @param host_name: a string, AP host name.

        @raise TestError: when unable to unlock AP in datastore.

        """
        for ap_locker in self._locked_aps:
            if host_name == ap_locker.configurator.host_name:
                self.manager.unlock(hosts=[host_name])
                self._locked_aps.remove(ap_locker)
                return

        logging.error('Tried to unlock a host we have not locked (%s)?',
                      host_name)


    def unlock_aps(self):
        """Unlock APs after we're done."""
        # Make a copy of all of the hostnames to process

        host_names = list()
        for ap_locker in self._locked_aps:
            host_names.append(ap_locker.configurator.host_name)
        for host_name in host_names:
            self.unlock_one_ap(host_name)


    def unlock_and_reclaim_ap(self, host_name):
        """Unlock an AP but return it to the remaining batch of APs.

        @param host_name: a string, host name.
        """
        for ap_locker in self._locked_aps:
            if host_name == ap_locker.configurator.host_name:
                self.aps_to_lock.append(ap_locker)
                self.unlock_one_ap(host_name)
                return


    def unlock_and_reclaim_aps(self):
        """Unlock APs but return them to the batch of remining APs.

        unlock_aps() will remove the remaining APs from the list of all APs
        to process.  This method will add the remaining APs back to the pool
        of unprocessed APs.

        """
        # Add the APs back into the pool
        self.aps_to_lock.extend(self._locked_aps)
        self.unlock_aps()
