from pathlib import Path
from plone import api
from plone.app.z3cform.widgets.datetime import DatetimeWidget
from plone.app.z3cform.widgets.datetime import DateWidget
from plone.app.z3cform.widgets.select import AjaxSelectWidget
from plone.app.z3cform.widgets.singlecheckbox import SingleCheckBoxBoolWidget
from plone.app.z3cform.widgets.text import TextAreaWidget
from plone.app.z3cform.widgets.text import TextWidget
from plone.formwidget.namedfile.widget import NamedFileWidget
from plone.formwidget.namedfile.widget import NamedImageWidget
from ploneintranet.layout.testing import IntegrationTestCase
from ploneintranet.layout.widgets.checkbox import PIMinimalCheckBoxWidget
from ploneintranet.layout.widgets.file import MultipleFileInputWidget
from ploneintranet.layout.widgets.miller_columns import PIContentBrowserWidget
from ploneintranet.layout.widgets.select import PIGooglePlaceSelectWidget
from ploneintranet.layout.widgets.select import PISelectFromOptgroupsWidget
from ploneintranet.layout.widgets.select import PISelectWidget
from ploneintranet.layout.widgets.text import PIEmailWidget
from ploneintranet.layout.widgets.text import PIURIWidget
from ploneintranet.layout.widgets.text import TelephoneWidget
from z3c.form.browser.checkbox import CheckBoxWidget
from z3c.form.browser.radio import RadioWidget
from z3c.form.interfaces import IWidgetLayoutTemplate
from zope.component import getMultiAdapter
from zope.pagetemplate.interfaces import IPageTemplate

import ploneintranet.layout.widgets

pi_templates_path = Path(ploneintranet.layout.widgets.__file__).parent / "templates"


class TestWidgets(IntegrationTestCase):
    maxDiff = None

    def setUp(self):
        """Custom shared utility setup for tests."""
        self.portal = self.layer["portal"]
        self.request = self.layer["request"]

    def test_custom_error(self):
        """Verify that we have properly registered the custom error view widget"""
        view = api.content.get_view("edit", self.portal, self.request)
        view.update()
        view.form_instance.handleApply(view.form_instance, None)
        self.assertEqual(
            view.form_instance.widgets["IDublinCore.title"].error.render().strip(),
            '<em class="message warning" >Required input is missing.</em>',
        )

    def test_custom_buttons(self):
        """Verify that we have properly registered the custom buttons widget"""
        view = api.content.get_view("edit", self.portal, self.request)
        view.update()
        actions = view.form_instance.actions
        self.assertEqual(
            actions["save"].render().strip(),
            '<button class="submit-widget btn btn-primary pat-button default icon-ok-circle success" '  # noqa: E501
            'id="form-buttons-save" '
            'name="form.buttons.save" '
            'type="submit" '
            'value="Save" >Save</button>',
        )

        # Check that we can set the formnovalidate attribute on the a button
        cancel_button = actions["cancel"]
        cancel_button.ignoreRequiredOnValidation = True
        self.assertEqual(
            actions["cancel"].render().strip(),
            '<button class="submit-widget btn btn-secondary pat-button icon-cancel-circle secondary" '  # noqa: E501
            'id="form-buttons-cancel" '
            'formnovalidate="formnovalidate" '
            'name="form.buttons.cancel" '
            'type="submit" '
            'value="Cancel" >Cancel</button>',
        )

    def test_custom_widgets(self):
        component_library = api.content.get_view("component-library", self.portal)
        component_library.update()
        self.assertDictEqual(
            {
                name: widget.__class__
                for name, widget in component_library.widgets.items()
            },
            {
                "auto_suggest_multiple": AjaxSelectWidget,
                "auto_suggest_single": AjaxSelectWidget,
                "auto_suggest_with_adding": AjaxSelectWidget,
                "auto_suggest_with_value": AjaxSelectWidget,
                "boolean": SingleCheckBoxBoolWidget,
                "boolean_extra_accessible": SingleCheckBoxBoolWidget,
                "boolean_extra_long": SingleCheckBoxBoolWidget,
                "boolean_minimal": PIMinimalCheckBoxWidget,
                "checklist_checkbox": CheckBoxWidget,
                "checklist_radio": RadioWidget,
                "date_and_time": DatetimeWidget,
                "date_picker": DateWidget,
                "email": PIEmailWidget,
                "file": NamedFileWidget,
                "image": NamedImageWidget,
                "images": MultipleFileInputWidget,
                "phone": TelephoneWidget,
                "primary_location": PIGooglePlaceSelectWidget,
                "select": PISelectWidget,
                "select_from_optgroups": PISelectFromOptgroupsWidget,
                "source": PIContentBrowserWidget,
                "text_input": TextWidget,
                "textarea": TextAreaWidget,
                "website": PIURIWidget,
            },
        )

    def test_custom_layout_template(self):
        """We have registered a custom layout template for the input widgets

        This wraps the widget in some markup
        """
        component_library = api.content.get_view("component-library", self.portal)
        component_library.update()

        widget_layout_templates = {
            getMultiAdapter(
                (widget.context, self.request, component_library, widget.field, widget),
                IWidgetLayoutTemplate,
                name="input",
            ).filename
            for widget in component_library.widgets.values()
        }
        self.assertEqual(
            {str(pi_templates_path / "widget_input_layout.pt")},
            widget_layout_templates,
        )

    def test_custom_widget_templates(self):
        """Check the template used to render the widgets in the form"""
        component_library = api.content.get_view("component-library", self.portal)
        component_library.update()

        widget_templates = {
            name: getMultiAdapter(
                (widget.context, self.request, component_library, widget.field, widget),
                IPageTemplate,
                name="input",
            ).filename
            for name, widget in component_library.widgets.items()
        }

        self.assertDictEqual(
            widget_templates,
            {
                "auto_suggest_multiple": str(pi_templates_path / "ajaxselect_input.pt"),
                "auto_suggest_single": str(pi_templates_path / "ajaxselect_input.pt"),
                "auto_suggest_with_adding": str(
                    pi_templates_path / "ajaxselect_input.pt"
                ),
                "auto_suggest_with_value": str(
                    pi_templates_path / "ajaxselect_input.pt"
                ),
                "boolean": str(pi_templates_path / "checkbox_input.pt"),
                "boolean_extra_accessible": str(
                    pi_templates_path / "checkbox_input.pt"
                ),
                "boolean_extra_long": str(pi_templates_path / "checkbox_input.pt"),
                "boolean_minimal": str(pi_templates_path / "checkboxminimal_input.pt"),
                "checklist_checkbox": str(pi_templates_path / "checkboxlist_input.pt"),
                "checklist_radio": str(pi_templates_path / "radio_input.pt"),
                "date_and_time": str(pi_templates_path / "date_time_input.pt"),
                "date_picker": str(pi_templates_path / "date_input.pt"),
                "email": str(pi_templates_path / "email_input.pt"),
                "file": str(pi_templates_path / "file_input.pt"),
                "image": str(pi_templates_path / "image_input.pt"),
                "images": str(pi_templates_path / "multiple_file_input.pt"),
                "phone": str(pi_templates_path / "text_input.pt"),
                "primary_location": str(pi_templates_path / "select_input.pt"),
                "select": str(pi_templates_path / "select_input.pt"),
                "select_from_optgroups": str(
                    pi_templates_path / "select_from_optgroups_input.pt"
                ),
                "source": str(pi_templates_path / "miller_columns_input.pt"),
                "text_input": str(pi_templates_path / "text_input.pt"),
                "textarea": str(pi_templates_path / "textarea_input.pt"),
                "website": str(pi_templates_path / "text_input.pt"),
            },
        )
