"""Utilities to manipulate hosts via UI."""
from robottelo.ui.base import Base
from robottelo.ui.locators import common_locators, locators, tab_locators
from robottelo.ui.navigator import Navigator


class Hosts(Base):
    """Provides the CRUD functionality for Host."""

    def navigate_to_entity(self):
        """Navigate to Hosts entity page"""
        Navigator(self.browser).go_to_hosts()

    def _search_locator(self):
        """Specify locator for Hosts entity search procedure"""
        return locators['host.select_name']

    def _configure_hosts_parameters(self, parameters_list):
        """Provide configuration capabilities for host entity generic
        properties.
        All values should be passed in absolute correspondence to UI. For
        example, we need to choose a value from 'Lifecycle environment' select
        list from 'Host' tab and input root password in corresponding field
        from 'Operating System' tab, so next parameter list should be passed::

            [
                ['Host', 'Lifecycle environment', 'Library'],
                ['Operating System', 'Root password', 'mynewpassword123'],
            ]

        """
        for tab_name, parameter_name, parameter_value in parameters_list:
            tab_locator = tab_locators['.tab_'.join((
                'host',
                (tab_name.lower()).replace(' ', '_')
            ))]
            param_locator = locators['.'.join((
                'host',
                (parameter_name.lower()).replace(' ', '_')
            ))]
            self.click(tab_locator)
            if parameter_name == 'Reset Puppet Environment':
                self.click(param_locator)
                continue
            # send_keys() can't send left parenthesis (see
            # SeleniumHQ/selenium#674), which is used in compute resource name
            # (e.g. 'test (Libvirt)')
            elif parameter_name == 'Deploy on' and ' (' in parameter_value:
                self.click(param_locator)
                # typing compute resource name without parenthesis part
                self.assign_value(
                    common_locators['select_list_search_box'],
                    parameter_value.split(' (')[0]
                )
                # selecting compute resource by its full name (with parenthesis
     
           # part)
                self.click(
                    common_locators[
'entity_select_list'] % parameter_value)
                continue
            elif parameter_name == 'Puppet Environment':
                # Make sure 'inherit' button is not pressed before selecting
                # puppet environment, as otherwise 'Puppet Environment'
                # dropdown will be disabled
                inherit = self.wait_until_element(
                    locators.host.inherit_puppet_environment)
                if 'active' in inherit.get_attribute('class'):
                    self.click(inherit)
            elif parameter_name == 'Compute profile':
                inherit = self.wait_until_element(
                    locators.host.inherit_compute_profile)
                if 'active' in inherit.get_attribute('class'):
                    self.click(inherit)
            self.assign_value(param_locator, parameter_value)

    def _configure_interface_parameters(self, parameters_list):
        """Provide configuration capabilities for host entity interface
        All values should be passed in absolute correspondence to UI. For
        example, we need to choose a value from 'Domain' select list and input
        MAC address in corresponding field, so next parameter list should be
        passed::

            [
                ['Domain', host.domain.name],
                ['MAC address', '16:76:20:06:d4:c0'],
            ]

        """
        for parameter_name, parameter_value in parameters_list:
            param_locator = locators['.interface_'.join((
                'host',
                (parameter_name.lower()).replace(' ', '_')
            ))]
            # send_keys() can't send left parenthesis (see
            # SeleniumHQ/selenium#674), which is a part of network type name
            # (e.g. 'Physical (Bridge)')
            if parameter_name == 'Network type' and ' (' in parameter_value:
                self.click(param_locator)
                # typing network type name without parenthesis part
                self.assign_value(
                    common_locators['select_list_search_box'],
                    parameter_value.split(' (')[0]
                )
                # selecting network type by its full name (with parenthesis
                # part)
                self.click(
                    common_locators['entity_select_list'] % parameter_value)
                continue
            self.assign_value(param_locator, parameter_value)
        self.click(locators['host.save_interface'])

    def _configure_provisioning_method(self, method):
        """Provide configuration capabilities for host to be created using
        provisioning methods. Eg.Boot disk based, Network Based, Image Based
        """
        self.click(tab_locators['host.tab_operating_system'])
        if method == 'bootdisk':
            self.click(tab_locators['operatingsys.tab_provision_bootdisk'])
        elif method == 'network':
            self.click(tab_locators['operatingsys.tab_provision_network'])
        elif method == 'image':
            self.click(tab_locators['operatingsys.tab_provision_images'])

    def _configure_puppet_modules(self, puppet_modules_list):
        """Provide configuration capabilities for host entity puppet classes
        tab.
        """
        self.click(tab_locators['host.tab_puppet_classes'])
        for puppet_module in puppet_modules_list:
            self.click(locators['host.select_puppetmodule'] % puppet_module)
            self.click(locators['host.select_puppetclass'] % puppet_module)

    def _add_host_parameters(self, parameters_list):
        """Add new host parameters for 'parameters' tab. Example::

        host_parameters=[['test01', 'value01'], ['test02', 'value02'],
        ['test03', 'value03']]

        """
        self.click(tab_locators['host.tab_params'])
        index = 1
        for parameter_name, parameter_value in parameters_list:
            self.click(locators['host.add_new_host_parameter'])
            self.assign_value(
                locators['host.host_parameter_name'] % index, parameter_name)
            self.assign_value(
                locators['host.host_parameter_value'] % index, parameter_value)
            index += 1

    def create(self, name, parameters_list=None, puppet_classes=None,
               interface_parameters=None, host_parameters=None,
               provisioning_method=None):
        """Creates a host."""
        self.click(locators['host.new'])
        self.assign_value(locators['host.name'], name)
        if parameters_list is not None:
            self._configure_hosts_parameters(parameters_list)
        if puppet_classes is not None:
            self._configure_puppet_modules(puppet_classes)
        if interface_parameters is not None:
            self.click(tab_locators['host.tab_interfaces'])
            self.click(locators['host.edit_default_interface'])
            self._configure_interface_parameters(interface_parameters)
        if host_parameters is not None:
            self._add_host_parameters(host_parameters)
        if provisioning_method is not None:
            self.click(tab_locators['host.tab_operating_system'])
            self._configure_provisioning_method(provisioning_method)
        self.wait_until_element_is_not_visible(
            common_locators['modal_background'])
        self.click(common_locators['submit'])

    def update(self, name, domain_name, new_name=None, parameters_list=None,
               puppet_classes=None, interface_parameters=None,
               host_parameters=None):
        """Updates a Host."""
        self.search_and_click(u'{0}.{1}'.format(name, domain_name))
        self.click(locators['host.edit'])
        if new_name:
            self.assign_value(locators['host.name'], new_name)
        if param