# -*- coding: utf-8 -*-
import attr
from copy import copy
from cached_property import cached_property
from navmazing import NavigateToAttribute, NavigateToSibling
from widgetastic.utils import ParametrizedLocator
from widgetastic.widget import Table, Text, View, ParametrizedView, Select, ClickableMixin
from widgetastic_manageiq import SummaryFormItem, ScriptBox, Input
from widgetastic_patternfly import BootstrapSelect, BootstrapSwitch, Button, CandidateNotFound
from cfme.exceptions import ItemNotFound
from cfme.modeling.base import BaseCollection, BaseEntity
from cfme.utils.appliance.implementations.ui import navigator, CFMENavigateStep, navigate_to
from cfme.utils.blockers import BZ
from cfme.utils.timeutil import parsetime
from cfme.utils.wait import wait_for
from . import AutomateExplorerView, check_tree_path
from .common import Copiable, CopyViewBase
from .klass import ClassDetailsView
class Inputs(View, ClickableMixin):
    ROOT = './/button[@id="exp_collapse_img"]/i'
    INDIRECT = True  # TODO: This appear to upset the parent lookup combined with ParView
    @property
    def is_opened(self):
        return 'fa-angle-up' in self.browser.classes(self)
    def child_widget_accessed(self, widget):
        if not self.is_opened:
            self.click()
    @ParametrizedView.nested
    class inputs(ParametrizedView):  # noqa
        PARAMETERS = ('name', )
        ROOT = ParametrizedLocator('//tr[./td[2]/input[normalize-space(@value)={name|quote}]]')
        ALL_FIELDS = '//div[@id="inputs_div"]/table//tr/td[2]/input'
        @cached_property
        def row_id(self):
            attr = self.browser.get_attribute(
                'id',
                './/td/input[contains(@id, "fields_name_")]',
                parent=self)
            return int(attr.rsplit('_', 1)[-1])
        name = Input(locator=ParametrizedLocator(
            './/td/input[contains(@id, "fields_name_{@row_id}")]'))
        data_type = Select(locator=ParametrizedLocator(
            './/td/select[contains(@id, "fields_datatype_{@row_id}")]'))
        default_value = Input(locator=ParametrizedLocator(
            './/td/input[contains(@id, "fields_value_{@row_id}")]'))
        @classmethod
        def all(cls, browser):
            results = []
            for e in browser.elements(cls.ALL_FIELDS):
                results.append((browser.get_attribute('value', e), ))
            return results
        def delete(self):
                self.browser.click(
                    './/img[@alt="Click to delete this input field from method"]', parent=self)
                try:
                    del self.row_id
                except AttributeError:
                    pass
    add_input = Text('//img[@alt="Equal green"]')
    name = Input(locator='.//td/input[contains(@id, "field_name")]')
    data_type = Select(locator='.//td/select[contains(@id, "field_datatype")]')
    default_value = Input(locator='.//td/input[contains(@id, "field_default_value")]')
    finish_add_input = Text('//img[@alt="Add this entry"]')
    def read(self):
        return self.inputs.read()
    def fill(self, value):
        keys = set(value.keys())
        value = copy(value)
        present = {key for key, _ in self.inputs.read().items()}
        to_delete = present - keys
        changed = False
        # Create the new ones
        for key in keys:
            if key not in present:
                new_value = value.pop(key)
                new_value['name'] = key
                self.add_input.click()
                super(Inputs, self).fill(new_value)
                self.finish_add_input.click()
                changed = True
        # Fill the rest as expected
        if self.inputs.fill(value):
            changed = True
        # delete unneeded
        for key in to_delete:
            self.inputs(name=key).delete()
            changed = True
        return changed
class MethodCopyView(AutomateExplorerView, CopyViewBase):
    @property
    def is_displayed(self):
        return (
            self.in_explorer and
            self.title.text == 'Copy Automate Method' and
            self.datastore.is_opened and
            check_tree_path(
                self.datastore.tree.currently_selected,
                self.context['object'].tree_path))
class MethodDetailsView(AutomateExplorerView):
    title = Text('#explorer_title_text')
    fqdn = SummaryFormItem(
        'Main Info', 'Fully Qualified Name',
        text_filter=lambda text: [item.strip() for item in text.strip().lstrip('/').split('/')])
    name = SummaryFormItem('Main Info', 'Name')
    display_name = SummaryFormItem('Main Info', 'Display Name')
    location = SummaryFormItem('Main Info', 'Location')
    created_on = SummaryFormItem('Main Info', 'Created On', text_filter=parsetime.from_iso_with_utc)
    inputs = Table(locator='#params_grid', assoc_column='Input Name')
    @property
    def is_displayed(self):
        return (
            self.in_explorer and
            self.title.text.startswith('Automate Method [{}'.format(
                self.context['object'].display_name or self.context['object'].name)) and
            self.fqdn.is_displayed and
            # We need to chop off the leading Domain name.
            self.fqdn.text == self.context['object'].tree_path_name_only[1:])
class PlaybookBootstrapSelect(BootstrapSelect):
    """BootstrapSelect widget for Ansible Playbook Method form.
    BootstrapSelect widgets don't have ``data-id`` attribute in this form, so we have to override
    ROOT locator.
    """
    ROOT = ParametrizedLocator('.//select[normalize-space(@name)={@id|quote}]/..')
class ActionsCell(View):
    edit = Button(**{"ng-click": "vm.editKeyValue(this.arr[0], this.arr[1], this.arr[2], $index)"})
    delete = Button(**{"ng-click": "vm.removeKeyValue($index)"})
class PlaybookInputParameters(View):
    """Represents input parameters part of playbook method edit form.
    """
    input_name = Input(name="provisioning_key")
    default_value = Input(name="provisioning_value")
    provisioning_type = PlaybookBootstrapSelect("provisioning_type")
    add_button = Button(**{"ng-click": "vm.addKeyValue()"})
    variables_table = Table(
        ".//div[@id='inputs_div']//table",
        column_widgets={"Actions": ActionsCell()}
    )
    def _values_to_remove(self, values):
        return list(set(self.all_vars) - set(values))
    def _values_to_add(self, values):
        return list(set(values) - set(self.all_vars))
    def fill(self, values):
        """
        Args:
            values (list): [] to remove all vars or [("var", "value", "type"), ...] to fill the view
        """
        if set(values) == set(self.all_vars):
            return False
        else:
            for value in self._values_to_remove(values):
                rows = list(self.variables_table)
                for row in rows:
                    if row[0].text == value[0]:
                        row["Actions"].widget.delete.click()
                        break
            for value in self._values_to_add(values):
                self.input_name.fill(value[0])
                self.default_value.fill(value[1])
                self.provisioning_type.fill(value[2])
                self.add_button.click()
            return True
    @property
    def all_vars(self):
        if self.variables_table.is_displayed:
            return [(row["Input Name"].text, row["Default value"].text, row["Data Type"].text) for
                    row in self.variables_table]
        else:
            return []
    def read(self):
        return self.all_vars
class MethodAddView(AutomateExplorerView):
    title = Text('#explorer_title_text')
    location = BootstrapSelect('cls_method_location', can_hide_on_select=True)
    inline_name = Input(name='cls_method_name')
    inline_display_name = Input(name='cls_method_display_name')
    script = ScriptBox()
    data = Input(name='cls_method_data')
    validate_button = Button('Validate')
    inputs = View.nested(Inputs)
    playbook_name = Input(name='name')
    playbook_display_name = Input(name='display_name')
    repository = PlaybookBootstrapSelect('provisioning_repository_id')
    playbook = PlaybookBootstrapSelect('provisioning_playbook_id')
    machine_credential = PlaybookBootstrapSelect('provisioning_machine_credential_id')
    hosts = Input('provisioning_inventory')
    max_ttl = Input('provisioning_execution_ttl')
    escalate_privilege = BootstrapSwitch('provisioning_become_enabled')
    verbosity = PlaybookBootstrapSelect('provisioning_verbosity')
    playbook_input_parameters = PlaybookInputParameters()
    add_button = Button('Add')


Answer:     cancel_button = Button('Cancel')