# This file is part of Tryton.  The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, Id
from trytond.model import (ModelSQL, ModelView, sort)
from trytond.tools import is_full_text, lstrip_wildcard
from trytond.transaction import Transaction, inactive_records
from decimal import getcontext, Decimal, ROUND_HALF_UP
from sql.aggregate import Count, Max, Min, Sum, Avg, BoolOr
from sql.conditionals import Case
from sql import Column, Literal
from sql.functions import CurrentTimestamp, DateTrunc
from trytond.wizard import Button, StateTransition, StateView, Wizard
from itertools import chain, groupby
from operator import itemgetter
import datetime
import logging

logger = logging.getLogger(__name__)

EVENT_TYPE = [
    ('fee', 'Fee'),
    ('wr', 'Weight report'),
    ('doc', 'Document'),
    ('date', 'Date'),
    ('wiz', 'Wizard'),
    ]

class ExecutionPlan(ModelSQL,ModelView):
    "Execution plan"
    __name__ = 'workflow.plan'
    _rec_name = 'name'

    purchase = fields.Many2One('purchase.purchase',"Purchase")
    execution = fields.Many2One('workflow.plan',"Plan")
    name = fields.Char("Name")
    from_location = fields.Many2One('stock.location', 'From location')
    to_location = fields.Many2One('stock.location', 'To location')
    from_to = fields.Integer("From_to")
    duration = fields.Integer("Duration")
    childs = fields.One2Many('workflow.plan','execution',"Childs")
    events_inherit = fields.Function(fields.One2Many('workflow.event','execution',
            "Events",
            # add_remove=[
            #     ('execution', '=', None),
            #     ],
            order=[
                ('sequence', 'ASC'),
                ],),'get_events', setter='set_events')
    events = fields.One2Many('workflow.event','execution',"Events")

    @fields.depends('from_location','to_location')
    def on_change_with_from_to(self):
        return abs(self.from_location.id - self.to_location.id)

    def get_ordered_childs(self):
        ordered_children = []
        if self.childs:
            childs = sort(self.childs, [('from_location','ASC'),('from_to','ASC')])
            logger.info("ORDEREDCHILDS:%s",childs)
            from_dict = {child.from_location.id: child for child in childs if child.from_location != child.to_location}
            current_from = self.from_location.id
            if current_from not in from_dict:
                ordered_children.extend([e.id for e in self.childs if e.from_location.id == e.to_location.id and e.from_location.id == self.from_location.id])
            while current_from in from_dict:
                ordered_children.extend([e.id for e in self.childs if e.from_location.id == e.to_location.id and e.from_location.id == current_from])
                current_child = from_dict[current_from]
                ordered_children.append(current_child)
                current_from = current_child.to_location.id    
        return ordered_children            

    def get_events_ordered(self):
        events = []
        Plan = Pool().get('workflow.plan')
        Event = Pool().get('workflow.event')
        events.extend(Event.search([('execution','=',self.id),('period','in',['from','transit'])],order=[('sequence','ASC')]))
        if self.childs:
            childs = self.get_ordered_childs()
            for c in childs:
                events.extend(Plan(c).get_events_ordered())
        events.extend(Event.search([('execution','=',self.id),('period','=','to')],order=[('sequence','ASC')]))
        logger.info("EVENTORDERED:%s",events)
        logger.info("EVENTORDERED2:%s",self.id)
        return events
    
    def get_events(self, name):
        return self.get_events_ordered()
        
    @classmethod
    def set_events(cls, executionplans, name, value):
        logger.info("SETEVENT:%s",value)
        if not value:
            return
        if value[0][0] == 'add':
            Event = Pool().get('workflow.event')
            ev = Event.search([('execution','=',executionplans[0].id),('id','in',value[0][1])])
            if not ev:
                return
        cls.write(executionplans, {
                'events': value,
                })
    
class Event(ModelSQL,ModelView):
    "Event"
    __name__ = 'workflow.event'

    #root = fields.Many2One('workflow.plan',"Root plan")
    execution = fields.Many2One('workflow.plan',"Plan")
    exe = fields.Function(fields.Many2One('workflow.plan',"Plan"),'get_exe')
    period = fields.Selection([('all','All'),('from','From'),('transit','Transit'),('to','To')],"Period")
    type = fields.Selection(EVENT_TYPE,"Event type")
    target = fields.Many2One('workflow.relation',"Target",domain=[('type','=',Eval('type'))])
    option = fields.One2Many('workflow.option.line','event',"Options",domain=[('event.type','=',Eval('type'))])
    warning = fields.Boolean("Warning")
    sequence = fields.Integer("Sequence")

    def get_exe(self,name):
        if self.execution:
            return self.execution

class Relation(ModelSQL,ModelView):
    "Relation"
    __name__ = 'workflow.relation'
    type = fields.Selection(EVENT_TYPE,"Event type")
    name = fields.Char("Name")

class Option(ModelSQL,ModelView):
    "Option"
    __name__ = 'workflow.option'
    type = fields.Selection(EVENT_TYPE,"Event type")
    name = fields.Char("Name")

class OptionLine(ModelSQL,ModelView):
    "Option line"
    __name__ = 'workflow.option.line'
    event = fields.Many2One('workflow.event',"Event")
    option = fields.Many2One('workflow.option',"Option")
