# -*- coding: utf-8 -*-
#
# This file is part of SENAITE.CORE
#
# Copyright 2018 by it's authors.
# Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst.

from AccessControl import getSecurityManager
from AccessControl.Permissions import view
from bika.lims import bikaMessageFactory as _
from bika.lims.browser import BrowserView
from bika.lims.interfaces import IHeaderTableFieldRenderer
from bika.lims.utils import t
from Products.CMFPlone import PloneMessageFactory as _p
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.component import getAdapter
from zope.component.interfaces import ComponentLookupError


class HeaderTableView(BrowserView):
    """Table rendered at the top in AR View
    """
    template = ViewPageTemplateFile("templates/header_table.pt")

    def __call__(self):
        self.errors = {}
        if "header_table_submitted" in self.request:
            schema = self.context.Schema()
            fields = schema.fields()
            form = self.request.form
            for field in fields:
                fieldname = field.getName()
                if fieldname in form:
                    # Handle (multiValued) reference fields
                    # https://github.com/bikalims/bika.lims/issues/2270
                    uid_fieldname = "{}_uid".format(fieldname)
                    if uid_fieldname in form:
                        value = form[uid_fieldname]
                        if field.multiValued:
                            value = value.split(",")
                        field.getMutator(self.context)(value)
                    else:
                        # other fields
                        field.getMutator(self.context)(form[fieldname])
            message = _p("Changes saved.")
            self.context.plone_utils.addPortalMessage(message, "info")
        return self.template()

    def three_column_list(self, input_list):
        list_len = len(input_list)

        # Calculate the length of the sublists
        sublist_len = (list_len % 3 == 0 and list_len / 3 or list_len / 3 + 1)

        def _list_end(num):
            # Calculate the list end point given the list number
            return num == 2 and list_len or (num + 1) * sublist_len

        # Generate only filled columns
        final = []
        for i in range(3):
            column = input_list[i * sublist_len:_list_end(i)]
            if len(column) > 0:
                final.append(column)
        return final

    def render_field_view(self, field):
        fieldname = field.getName()
        field = self.context.Schema()[fieldname]
        ret = {"fieldName": fieldname, "mode": "view"}
        try:
            adapter = getAdapter(self.context,
                                 interface=IHeaderTableFieldRenderer,
                                 name=fieldname)

        except ComponentLookupError:
            adapter = None
        if adapter:
            ret = {'fieldName': fieldname,
                   'mode': 'structure',
                   'html': adapter(field)}
        else:
            if field.getWidgetName() == "BooleanWidget":
                value = field.get(self.context)
                ret = {
                    "fieldName": fieldname,
                    "mode": "structure",
                    "html": t(_("Yes")) if value else t(_("No"))
                }
            elif field.getType().find("Reference") > -1:
                # Prioritize method retrieval over schema"s field
                targets = None
                if hasattr(self.context, "get%s" % fieldname):
                    fieldaccessor = getattr(self.context, "get%s" % fieldname)
                    if callable(fieldaccessor):
                        targets = fieldaccessor()
                if not targets:
                    targets = field.get(self.context)

                if targets:
                    if not type(targets) == list:
                        targets = [targets, ]
                    sm = getSecurityManager()
                    if all([sm.checkPermission(view, ta) for ta in targets]):
                        elements = [
                            "<div id='{id}' class='field reference'>"
                            "  <a class='link' uid='{uid}' href='{url}'>"
                            "    {title}"
                            "  </a>"
                            "</div>"
                            .format(id=target.getId(),
                                    uid=target.UID(),
                                    url=target.absolute_url(),
                                    title=target.Title())
                            for target in targets]

                        ret = {
                            "fieldName": fieldname,
                            "mode": "structure",
                            "html": "".join(elements),
                        }
                    else:
                        ret = {
                            "fieldName": fieldname,
                            "mode": "structure",
                            "html": ", ".join([ta.Title() for ta in targets]),
                        }
                else:
                    ret = {
                        "fieldName": fieldname,
                        "mode": "structure",
                        "html": "",
                    }
            elif field.getType().lower().find("datetime") > -1:
                value = field.get(self.context)
                ret = {
                    "fieldName": fieldname,
                    "mode": "structure",
                    "html": self.ulocalized_time(value, long_format=True)
                }
        return ret

    def sublists(self):
        ret = []
        prominent = []
        context = self.context

        for field in context.Schema().fields():
            fieldname = field.getName()
            widget = field.widget
            state = widget.isVisible(
                context, "header_table", default="invisible", field=field)
            if state == "invisible":
                continue
            elif state == "prominent":
                if widget.isVisible(
                        context,
                        "edit", default="invisible", field=field) == "visible":
                    prominent.append({"fieldName": fieldname, "mode": "edit"})
                elif widget.isVisible(
                        context,
                        "view", default="invisible", field=field) == "visible":
                    prominent.append(self.render_field_view(field))
            elif state == "visible":
                if widget.isVisible(
                        context,
                        "edit", default="invisible", field=field) == "visible":
                    ret.append({"fieldName": fieldname, "mode": "edit"})
                elif widget.isVisible(
                        context,
                        "view", default="invisible", field=field) == "visible":
                    ret.append(self.render_field_view(field))
        return prominent, self.three_column_list(ret)
