# coding=utf-8

"""Homogeneous storage system.

.. moduleauthor:: Stéphane Vialette <vialette@gmail.com>

"""

from .storagesystem import StorageSystem
from .storagesystemsnapshotcontroller import SuspendedStorageSystemSnapshotController
from .storagesystemexception import StorageSystemException


class HomogeneousStorageSystem(StorageSystem):

    # storage system type
    TYPE = "homogeneous"

    def __init__(self, capacity, cpu, transfer_time_manager, name=None):
        """Initialize this homogeneous storage system.

        :param capacity: The capacity of each storage unit of this storage system.
        :type capacity: Numeric.
        :param cpu:The number of cpu of each storage unit of this storage system.
        :type cpu: int.

        """
        super(self.__class__, self).__init__(transfer_time_manager, name)

        # capacity
        if capacity <= 0:
            raise StorageSystemException("non-positive capacity '{}'".format(capacity))
        self._capacity = capacity

        # cpu
        if cpu <= 0:
            raise StorageSystemException("non-positive cpu '{}'".format(cpu))
        if not isinstance(cpu, int):
            raise StorageSystemException("non-integer cpu '{}'".format(cpu))
        self._cpu = cpu

    @property
    def capacity(self):
        """Return the capacity of each storage unit.
        """
        return self._capacity

    @property
    def cpu(self):
        """Return the number of cpu of each storage unit.
        """
        return self._cpu

    def add_storage_unit(self, environment, storage_unit_name = None):
        """Add a new storage unit to this storage system.
        """
        return super(self.__class__, self).add_storage_unit(environment, self.capacity, self.cpu, storage_unit_name)


def homogeneous_storage_system_builder(environment, number_of_storage_units, capacity, cpu, transfer_time_manager,
                                       name=None,
                                       storage_unit_names = None):
    """Convenient function to create an homogeneous storage system.

    :param number_of_storage_units: The number of storage units to be created.
    :type number_of_storage_units: int.
    :param capacity: The capacity of each storage unit.
    :type capacity: Numeric.
    :param cpu: The number of cpu of each storag unit.
    :type cpu: int.
    :param name: An optional name for this storage system.
    :type name: string.
    :param storage_unit_names: An optional list of names for the storage units.
    :type storage_unit_names: [string].

    """
    # number of storage units
    if not isinstance(number_of_storage_units, int):
        raise StorageSystemException("non-integer number of storage units")
    if number_of_storage_units < 0:
        raise StorageSystemException("negative number of storage units")

    # take care of storage unit names
    if storage_unit_names is not None:
        if len(storage_unit_names) != number_of_storage_units:
            msg = "bad number of storage unit names, expected {} got {}".format(number_of_storage_units, len(storage_unit_names))
            raise StorageSystemException(msg)

    # create the storage system
    homogeneous_storage_system = HomogeneousStorageSystem(capacity, cpu, transfer_time_manager, name)

    # suspend the storage system snapshot controller while we are adding
    # the storage units.
    with SuspendedStorageSystemSnapshotController(homogeneous_storage_system):
        # add the storage units to the storage system
        for i in range(number_of_storage_units):
            storage_unit_name = None
            if storage_unit_names is not None:
                storage_unit_name = storage_unit_names[i]
            homogeneous_storage_system.add_storage_unit(environment, storage_unit_name)

    # let the snapshot controller know about the new storage units
    homogeneous_storage_system.force_snapshot(environment)

    # return back to the caller the new storage system
    return homogeneous_storage_system
