from datetime import date

from cubicweb.entities import AnyEntity, fetch_config
from cubicweb.predicates import is_instance

from cubicweb_iprogress.entities import IMileStoneAdapter, IProgressAdapter


class Order(AnyEntity):
    __regid__ = 'Order'
    fetch_attrs, cw_fetch_order = fetch_config(('title', 'date'))

    def update_progress(self, compute=True):
        """callable only on the server side"""
        if compute:
            workorders = self.split_into
            self.cw_set(
                budget=sum(wod.budget or 0 for wod in workorders),
                progress_done=sum(wod.progress_done or 0 for wod in workorders),
                progress_todo=sum(wod.progress_todo or 0 for wod in workorders))


class WorkOrder(AnyEntity):
    __regid__ = 'WorkOrder'

    fetch_attrs, cw_fetch_order = fetch_config(('title', 'description_format',
                                                'description', 'budget',
                                                'begin_date', 'end_date', 'in_state'))

    def dc_title(self):
        return self.title

    def dc_long_title(self):
        return u'%s - %s' % (self.order.dc_title(), self.title)

    @property
    def order(self):
        return self.reverse_split_into[0]

    def update_progress(self, compute=True):
        """callable only on the server side"""
        for order in self.reverse_split_into:
            order.update_progress(True)


class WorkOrderIMileStoneAdapter(IMileStoneAdapter):
    __select__ = is_instance('WorkOrder')
    parent_type = 'Order'

    def get_main_task(self):
        return self.entity.order

    def initial_prevision_date(self):
        """returns the initial expected end of the milestone

        Warning: not taken into accound WorkOrder transition/state.
        """
        return self.entity.end_date or date.today()

    def eta_date(self):
        """returns expected date of completion based on what remains
        to be done

        Warning: not taken into accound WorkOrder transition/state.
        """
        if not self.entity.end_date or date.today() > self.entity.end_date:
            return date.today()
        return self.entity.end_date

    def completion_date(self):
        """returns date on which the subtask has been completed"""
        return date.today()

    def contractors(self):
        """returns the list of persons supposed to work on this task"""
        return []

    def in_progress(self):
        return self.entity.cw_adapt_to('IWorkflowable').state == u'in progress'

    def progress_info(self):
        return {'estimated': self.entity.budget,
                'estimatedcorrected': self.entity.budget,
                'done': self.entity.progress_done,
                'todo': self.entity.progress_todo}


# XXX IMileStone / IProgress inheritance stink
class WorkOrderProgressAdapter(WorkOrderIMileStoneAdapter):
    __regid__ = 'IProgress'
    __select__ = is_instance('WorkOrder')


class OrderProgressAdapter(IProgressAdapter):
    __select__ = is_instance('Order')

    def progress_info(self):
        return {'estimated': self.entity.budget,
                'estimatedcorrected': self.entity.budget,
                'done': self.entity.progress_done,
                'todo': self.entity.progress_todo,
                }

    def in_progress(self):
        return True  # FIXME


class OrderIMileStoneAdapter(IMileStoneAdapter):
    __select__ = is_instance('Order')

    def get_main_task(self):
        return self.entity

    def initial_prevision_date(self):
        """returns the initial expected end of the milestone"""
        return date.today()

    def eta_date(self):
        """returns expected date of completion based on what remains
        to be done
        """
        return date.today()

    def completion_date(self):
        """returns date on which the subtask has been completed"""
        return date.today()

    def contractors(self):
        """returns the list of persons supposed to work on this task"""
        return []

    def in_progress(self):
        return self.entity.cw_adapt_to('IWorkflowable').state == u'in progress'

    def progress_info(self):
        return {'estimated': self.entity.budget,
                'estimatedcorrected': self.entity.budget,
                'done': self.entity.progress_done,
                'todo': self.entity.progress_todo}
