# -*- coding: utf-8 -*-

import collections

import six

from bika.lims import api
from bika.lims.browser import BrowserView
from bika.lims.interfaces import IAnalysisRequest
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from senaite.core import logger

OFF_VALUES = ["0", "off", "no"]


class MultiResultsView(BrowserView):
    """Allows to edit results of multiple samples
    """
    template = ViewPageTemplateFile("templates/multi_results.pt")

    def __init__(self, context, request):
        super(MultiResultsView, self).__init__(context, request)
        self.context = context
        self.request = request
        self.portal = api.get_portal()

    def __call__(self):
        return self.template()

    @property
    def context_state(self):
        return api.get_view(
            "plone_context_state",
            context=self.context, request=self.request)

    def contents_table(self, sample, poc):
        view_name = "table_{}_analyses".format(poc)
        view = api.get_view(view_name, context=sample, request=self.request)
        # Inject additional hidden field in the listing form for redirect
        # https://github.com/senaite/senaite.app.listing/pull/80
        view.additional_hidden_fields = [{
            "name": "redirect_url",
            "value": self.context_state.current_page_url(),
        }]
        view.update()
        view.before_render()
        return view.contents_table()

    def show_lab_analyses(self, sample):
        """Show/Hide lab analyses
        """
        analyses = sample.getAnalyses(getPointOfCapture="lab")
        if len(analyses) == 0:
            return False
        lab_analyses = self.request.get("lab_analyses")
        if lab_analyses in OFF_VALUES:
            return False
        return True

    def show_field_analyses(self, sample):
        """Show/Hide field analyses
        """
        analyses = sample.getAnalyses(getPointOfCapture="field")
        if len(analyses) == 0:
            return False
        field_analyses = self.request.get("field_analyses", True)
        if field_analyses in OFF_VALUES:
            return False
        return True

    def get_samples(self):
        """Extract the samples from the request UIDs

        This might be either a samples container or a sample context
        """

        # fetch objects from request
        objs = self.get_objects_from_request()

        samples = []

        for obj in objs:
            # when coming from the samples listing
            if IAnalysisRequest.providedBy(obj):
                samples.append(obj)

        # when coming from the WF menu inside a sample
        if IAnalysisRequest.providedBy(self.context):
            samples.append(self.context)

        return self.uniquify_items(samples)

    def uniquify_items(self, items):
        """Uniquify the items with sort order
        """
        unique = []
        for item in items:
            if item in unique:
                continue
            unique.append(item)
        return unique

    def get_objects_from_request(self):
        """Returns a list of objects coming from the "uids" request parameter
        """
        unique_uids = self.get_uids_from_request()
        return filter(None, map(self.get_object_by_uid, unique_uids))

    def get_uids_from_request(self):
        """Return a list of uids from the request
        """
        uids = self.request.form.get("uids", "")
        if isinstance(uids, six.string_types):
            uids = uids.split(",")
        unique_uids = collections.OrderedDict().fromkeys(uids).keys()
        return filter(api.is_uid, unique_uids)

    def get_object_by_uid(self, uid):
        """Get the object by UID
        """
        logger.debug("get_object_by_uid::UID={}".format(uid))
        obj = api.get_object_by_uid(uid, None)
        if obj is None:
            logger.warn("!! No object found for UID #{} !!")
        return obj
