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

from openerp import models, fields, api, exceptions, _
import datetime
import pytz
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
from openerp.exceptions import except_orm, Warning, RedirectWarning

__INSERT_DATA__ = False
CONFIRMED_ACTUAL = 'confirmed_actual'
CONFIRMED_PREVIOUS = 'confirmed_previous'
AUTHORIZED_ACTUAL = 'authorized_actual'
AUTHORIZED_PREVIOUS = 'authorized_previous'
DRAFT = 'draft'

    
def gt_eq_zero(num):
    return num >= 0

def control_dates(my_period, its_period):
    my_start_date = datetime.datetime.strptime(my_period.start_date, DEFAULT_SERVER_DATETIME_FORMAT)
    my_end_date = datetime.datetime.strptime(my_period.end_date, DEFAULT_SERVER_DATETIME_FORMAT)
    its_start_date = datetime.datetime.strptime(its_period.start_date, DEFAULT_SERVER_DATETIME_FORMAT)
    its_end_date = datetime.datetime.strptime(its_period.end_date, DEFAULT_SERVER_DATETIME_FORMAT)
    
    """Controls:
    1st line: the is no old period start hour in middle of the new period 
    2nd line: the is no old period end hour in middle of the new period 
    3st line: the new period end hour is not in middle of any old period """            
    return (gt_eq_zero((my_start_date - its_start_date).days) != gt_eq_zero((my_end_date - its_start_date).days)) \
        or (gt_eq_zero((my_start_date - its_end_date).days) != gt_eq_zero((my_end_date - its_end_date).days)) \
        or (gt_eq_zero((its_start_date - my_end_date).days) != gt_eq_zero((its_end_date - my_end_date).days))

class RoutePeriodPoint(models.Model):
    _name = 'route.period.point'
    _inherit = ['mail.thread']

    _track = {
        'state': {
            'rafalim_route_calendar.mt_route_confirmed': lambda self, cr, uid, obj, ctx=None: obj.state in [CONFIRMED_ACTUAL,CONFIRMED_PREVIOUS],
            'rafalim_route_calendar.mt_route_authorized': lambda self, cr, uid, obj, ctx=None: obj.state in [AUTHORIZED_ACTUAL,AUTHORIZED_PREVIOUS],
        },
    }

    @api.multi
    def _get_repositor(self):
        user_id = self.env.user.id
        res = self.env['res.repositor'].search([('user_id', '=', user_id)])
        is_route_admin = self.env.user.has_group('rafalim_route_calendar.group_routing_admin')
        if not res and not is_route_admin:
            raise except_orm(_("Repositor error!"), _("You cannot load routing information "\
                    "because you are not a Repositor nor Route Admin"))
        if is_route_admin:
            return False

        return res.id

    name = fields.Char(size=64, string='Name', compute='_get_name', readonly=True)
    repositor_id = fields.Many2one('res.repositor',default=_get_repositor,string='Repositor')#, required=True)
    start_date = fields.Datetime(required=True, string='Start Date', states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]})
    end_date = fields.Datetime(required=True, string='End Date', states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]})
    duration = fields.Float(digits=(2,2),compute='_get_duration', string='Duration', help='Duration in hours',store=True, readonly=True)
    partner_id = fields.Many2one('res.partner', string='Client', required=True, states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]})
    region_id = fields.Many2one('geographic.zone', string='Region', compute='_get_region', store=True)
    commercial_zone_id = fields.Many2one('commercial.zone', string='Commercial zone', compute='_get_commercial_zone', store=True)
    state = fields.Selection([
        (DRAFT, "Draft"),
        (CONFIRMED_PREVIOUS, "Confirmed"),
        (AUTHORIZED_PREVIOUS, "Authorized"),
        (CONFIRMED_ACTUAL, "Confirmed"),
        (AUTHORIZED_ACTUAL, "Authorized"),
    ], default=DRAFT, string='State', readonly=True)


    # TODO: Cambiar el compute por el valor segun el context de la action, ya que ahora lo
    # tenemos por separado cuando cargan efectivo y anticipado
    route_type = fields.Selection([
        ('previous', "Previous"),
        ('actual', "Actual"),
    ], string='Route Type', compute='_get_route_type', store=True, readonly=True)

    commentary = fields.Text(string='Commentaries', states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]})
    period_id = fields.Many2one('route.period', compute='_get_period',store=True, string='Supervisor period', states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]})
    calendar_week_id = fields.Many2one('calendar.year.week', string='Week', compute='_get_week', store=True, states={AUTHORIZED_PREVIOUS: [('readonly', True)],AUTHORIZED_ACTUAL: [('readonly', True)]})

    @api.onchange('repositor_id')
    def change_repositor(self):
        domain=[('requires_reposition', '=', True),
                ('id', 'in', sum(map(lambda zone: zone.customers.mapped('id'),self.repositor_id.zone_ids),[]))]

        return {'domain': {'partner_id': domain}}

    @api.depends('partner_id')
    def _get_region(self):
        for point in self:
            point.region_id = point.partner_id.sub_region_id.geographic_zone_id

    @api.depends('partner_id')
    def _get_commercial_zone(self):
        for point in self:
            point.commercial_zone_id = point.partner_id.commercial_zone_id

    @api.multi
    @api.depends('start_date', 'end_date', 'repositor_id')
    def _get_period(self):
        #Checks if the period exits, if not create it and assign it

        """
        import ipdb
        ipdb.set_trace()
        #"""

        # TODO: Chequear pr que en cierto momento vienen varios period.points. Ver el compute,
        # o tratar de evitarlo
        for point in self:
            calendar_week_id = self.env['calendar.year.week']._check_date(point.start_date)
            #calendar_week_id = self.env['calendar.year.week'].search(['&',('first_day','<=',self.start_date),('last_day','>=',self.start_date)])


            repositor_id = point.repositor_id #self.env['res.repositor'].search([('user_id','=',self.env.user.id)])

            if len(repositor_id.supervisor_id) > 0:
                period_id = self.env['route.period']._check_period(calendar_week_id,repositor_id)
                #period_id = self.env['route.period'].search(['&', ('calendar_week_id','=',calendar_week_id.id),('repositor_id','=',repositor_id.id)])
                #point.period_id = period_id
                point.update({"period_id": period_id.id})
                #self.repositor_id = period_id.repositor_id

            else:
                raise exceptions.ValidationError(_("You have none supervisor, please contact a system admin"))
    
    @api.depends('start_date')
    def _get_route_type(self):
        for route_period_point in self:
        
            """
            import pdb
            pdb.set_trace()
            #"""

            today = datetime.datetime.strptime(fields.Date.context_today(self), DEFAULT_SERVER_DATE_FORMAT)
            today = datetime.datetime(year=today.year, month=today.month, day=today.day, hour=5)

            to_next_monday_delta = datetime.timedelta(days=-today.weekday()+7)
            
            next_monday = today + to_next_monday_delta
        
            sdate = route_period_point.start_date

            compare_date = fields.Datetime.context_timestamp(self,datetime.datetime.strptime(sdate, DEFAULT_SERVER_DATETIME_FORMAT))

            sdate = compare_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)

            snext_monday = next_monday.strftime(DEFAULT_SERVER_DATETIME_FORMAT)

            if (snext_monday < sdate):
                #gt_eq_zero((next_monday - compare_date).days)): 
                #and gt_eq_zero((compare_date - last_monday).days)):
                route_period_point.route_type = 'previous'
            else:
                route_period_point.route_type = 'actual'

    @api.depends('period_id')
    def _get_week(self):
        for route_period_point in self:
            route_period_point.calendar_week_id = route_period_point.period_id.calendar_week_id

    @api.multi
    def action_confirm(self):
        if self.route_type == 'actual':
            if self.state != AUTHORIZED_ACTUAL:
                state = AUTHORIZED_ACTUAL
            else:
                state = CONFIRMED_ACTUAL
        else:
            state = CONFIRMED_PREVIOUS 

        self.message_post(body='Confirmado: \n * Inicio: %s \n * Fin: %s \n * Sucursal: %s \n * Semana: %s' %(self.start_date,self.end_date,self.partner_id.name,self.calendar_week_id.name))
        self.write({'state': state})
        return True

    @api.multi
    def action_delete(self):
        self.unlink()

    @api.multi
    def action_authorize(self):
        if self.state != DRAFT:
            if self.route_type == 'actual':
                state = AUTHORIZED_ACTUAL
            else:
                state = AUTHORIZED_PREVIOUS 
            self.write({'state': state})
            self.message_post(body='Autorizado.')

    @api.depends('period_id')
    @api.constrains('start_date', 'end_date')
    def _check_date(self):
        today = datetime.datetime.strptime(fields.Date.context_today(self), DEFAULT_SERVER_DATE_FORMAT)
        today = datetime.datetime(year=today.year, month=today.month, day=today.day, hour=5)
        to_monday_delta = datetime.timedelta(days=-today.weekday())
        week_delta = datetime.timedelta(days=7)

        last_monday = today + to_monday_delta
        next_monday = last_monday + week_delta
        
        group_id_supervisor = self.env.ref('supervisors_and_pools.group_salesman_supervisor')

        for route_period_point in self:
            start_date = fields.Datetime.context_timestamp(self,datetime.datetime.strptime(route_period_point.start_date, DEFAULT_SERVER_DATETIME_FORMAT))
            end_date = fields.Datetime.context_timestamp(self,datetime.datetime.strptime(route_period_point.end_date, DEFAULT_SERVER_DATETIME_FORMAT))
            if not __INSERT_DATA__:
                if group_id_supervisor not in self.env.user.groups_id:
                    if route_period_point.state != DRAFT:
                        raise exceptions.ValidationError(_("It is not an editable period"))

                if start_date.weekday() == 6:
                    raise exceptions.ValidationError(_("Can't assign a job on Sunday"))

                """
                import pdb
                pdb.set_trace()
                #"""

                control_line_ids = route_period_point.period_id.period_point_ids

                if not (start_date.day == end_date.day and start_date.month == end_date.month and start_date.year == end_date.year):
                    raise exceptions.ValidationError(_("Period must have the same start and end date"))
                start_date = datetime.datetime(year=start_date.year, month=start_date.month, day=start_date.day, hour=start_date.hour,minute=start_date.minute)

                #Controls if its the correct time to commit the period

                if route_period_point.route_type == 'previous':
                    next_monday_diff = start_date - next_monday
                    if next_monday_diff.days < 0 or next_monday_diff.days > 6:
                        raise exceptions.ValidationError(_("Should be the previous week to add a previous period"))
                elif route_period_point.route_type == 'actual':
                    last_monday_diff = start_date - last_monday
                    next_monday_diff = start_date - next_monday
                    if last_monday_diff.days < 0 or next_monday_diff.days > 0:
                        raise exceptions.ValidationError(_("Should be the same week to add an actual period"))

                #Controls collisiding hours
                for control_line in control_line_ids:
                    #control_line =  self.browse(control_line_id.id)

                    if control_line.id != route_period_point.id and control_line.route_type == route_period_point.route_type and control_dates(route_period_point,control_line):
                        raise exceptions.ValidationError(_("Can not have collisiding periods"))

    @api.model
    def process_comfirm_calendar_scheduler(self):
        state_to_upgrade = DRAFT

        #Contains all ids for the model route.period.point
        scheduler_line_ids = self.env['route.period.point'].search([('state','=',state_to_upgrade)])
        #Loops over every record in the model route.point.period
        for scheduler_line in scheduler_line_ids :

            state = scheduler_line.state

            #Comment section How to work if its not call at 5am
            """
            start_date = fields.Datetime.context_timestamp(self,datetime.datetime.strptime(scheduler_line.start_date, DEFAULT_SERVER_DATETIME_FORMAT))
            start_date = datetime.datetime(year=start_date.year, month=start_date.month, day=start_date.day, hour=start_date.hour,minute=start_date.minute)
            today = datetime.datetime.strptime(fields.Date.context_today(self), DEFAULT_SERVER_DATE_FORMAT)
            today = datetime.datetime(year=today.year, month=today.month, day=today.day, hour=5)
            """
            #Uncomment section
            start_date = datetime.datetime.strptime(scheduler_line.start_date, DEFAULT_SERVER_DATETIME_FORMAT)
            today = datetime.datetime.now()
        
            if scheduler_line.route_type == 'previous':
                if (start_date - today).days <= 7:
                    if state == DRAFT:
                        to_state = CONFIRMED_PREVIOUS
                        scheduler_line.write({'state': to_state, 'lastModified': today})

            if scheduler_line.route_type == 'actual':
                if (start_date - today).days <= 0:
                    if state == DRAFT:
                        to_state = CONFIRMED_ACTUAL
                        scheduler_line.write({'state': to_state, 'lastModified': today})

    @api.depends('partner_id', 'route_type', 'state')
    def _get_name(self):
        for route_period_point in self:
            route_period_point.name = "%s - %s - %s" % (route_period_point.partner_id.name, route_period_point.route_type, route_period_point.state)

    @api.multi
    def unlink(self):
        if not self.state == DRAFT:
            raise Warning(_('You cannot delete a route period point which is not draft.'))
        return models.Model.unlink(self)

#    @api.multi
#    def write(self, vals):
#        for route_period_point in self:
#            arr = self.env['crm.case.section'].search([('user_id','=',self.env.user.id)])
#
#            if len(arr) == 0:
#                if not self.state == 'draft' and not self.state == 'to_correct' :
#                    raise Warning(_('You cannot edit a route period point which is not draft.'))
#            elif len(vals) > 1:
#                if vals.get('state') != None:
#                    raise Warning(_('You cannot edit a route period point'))
#                if self.state == 'draft':
#                    raise Warning(_('You cannot authorize a draft route period point'))
#        return models.Model.write(self,vals)

    @api.depends('start_date','end_date')
    def _get_duration(self):
        for route_period_point in self:

            start_date = datetime.datetime.strptime(route_period_point.start_date, DEFAULT_SERVER_DATETIME_FORMAT)
            end_date = datetime.datetime.strptime(route_period_point.end_date, DEFAULT_SERVER_DATETIME_FORMAT)
            duration = end_date - start_date
            route_period_point.duration = duration.seconds/3600.0 

    #@api.multi
    #def fields_get(self):
    def fields_get(self, cr, uid, fields=None, context=None, write_access=True, attributes=None):
        res = super(RoutePeriodPoint, self).fields_get(cr, uid, fields, context, write_access, attributes)
        #res = super(RoutePeriodPoint, self).fields_get()
        
        #import ipdb
        #ipdb.set_trace()
        user_id = self.pool.get('res.users').browse(cr,uid,[uid],context=context)

        is_route_admin = user_id.has_group('rafalim_route_calendar.group_routing_admin')
        is_route_repositor = user_id.has_group('rafalim_route_calendar.group_repositor')
        is_route_supervisor = user_id.has_group('supervisors_and_pools.group_salesman_supervisor')

        fieldss = ['start_date','end_date','partner_id','commentary']

        ## REPEAT CODE  >  UNREADABLE CODE
        for field in fieldss:
            if field in res:
                res[field].setdefault('states', {})
                res[field]['states'][DRAFT] = [('readonly', False)]
                res[field]['states'][AUTHORIZED_ACTUAL] = [('readonly', True)]
                res[field]['states'][AUTHORIZED_PREVIOUS] = [('readonly', True)]
                if is_route_admin:
                    res[field]['states'][CONFIRMED_PREVIOUS] = [('readonly', False)]
                    res[field]['states'][CONFIRMED_ACTUAL] = [('readonly', False)]
                elif is_route_supervisor:
                    res[field]['states'][CONFIRMED_PREVIOUS] = [('readonly', False)]
                    res[field]['states'][CONFIRMED_ACTUAL] = [('readonly', True)]
                else:
                    res[field]['states'][CONFIRMED_PREVIOUS] = [('readonly', True)]
                    res[field]['states'][CONFIRMED_ACTUAL] = [('readonly', True)]
        if 'repositor_id' in res:
            res['repositor_id'].setdefault('states', {})
            res['repositor_id']['states'][CONFIRMED_PREVIOUS] = [('readonly', True)]
            res['repositor_id']['states'][CONFIRMED_ACTUAL] = [('readonly', True)]
            res['repositor_id']['states'][AUTHORIZED_ACTUAL] = [('readonly', True)]
            res['repositor_id']['states'][AUTHORIZED_PREVIOUS] = [('readonly', True)]
            if is_route_admin:
                res['repositor_id']['states'][DRAFT] = [('readonly', False)]
            else:
                res['repositor_id']['states'][DRAFT] = [('readonly', True)]
        
        return res


        """Add domain for user_id and member_ids fields on the supervisor's form
        base_url = self.env['ir.config_parameter'].get_param('web.base.url')
        action = self.env.ref('kilbel_hr_attendance_timetable.hr_holidays_selected_action')
        final_url = base_url + '/web#min=1&limit=80&view_type=list&model=hr.holidays&action=' + str(action.id)

        message_body = _('The holidays to pay attention are in %s') % (final_url)

        value = self.env["ir.config_parameter"].get_param("hr_holidays_renovate_partners", default='[]').replace('[','').replace(']','')
        value_list = value.encode('ascii').split(',')
        hr_holidays_renovate_partner_m2m_list = map(lambda x: (4,int(x),0), filter(lambda y: y != '', value_list))

        thread_pool = self.env['mail.thread']
        mess_id = thread_pool.message_post(
        message_type="notification",
        subtype="mt_comment",
        subject = "Message subject",
        body= message_body,
        )

        mess_id.write({"partner_ids" : hr_holidays_renovate_partner_m2m_list, "needaction_partner_ids": hr_holidays_renovate_partner_m2m_list})
        """

    @api.onchange('start_date','end_date','partner_id','commentary','state')
    def control_supervisor_changes(self):
        is_route_supervisor = self.env.user.has_group('supervisors_and_pools.group_salesman_supervisor')
        
        for route_period_point in self:
            if is_route_supervisor:
                #send message

                base_url = self.env['ir.config_parameter'].get_param('web.base.url')
                action = self.env.ref('rafalim_route_calendar.see_points')
                final_url = base_url + '/web#id='+ str(self._origin.id) +'&view_type=form&model=see_points&action=' + str(action.id)


                """Add domain for user_id and member_ids fields on the supervisor's form."""
                message_body = _('There are changes by your supervisor in the route period point at %s, the change are:') % (final_url)

                if self._origin.start_date != self.start_date:
                    message_body = message_body + '\n' +_('Start date %s -> %s') % (self._origin.start_date,self.start_date)
                if self._origin.end_date != self.end_date:
                    message_body = message_body + '\n' +_('End date %s -> %s') % (self._origin.end_date,self.end_date)
                if self._origin.partner_id != self.partner_id:
                    message_body = message_body + '\n' +_('Partner %s -> %s') % (self._origin.partner_id.name,self.partner_id.name)
                if self._origin.commentary != self.commentary:
                    message_body = message_body + '\n' +_('Commentary %s -> %s') % (self._origin.commentary,self.commentary)
                if self._origin.state != self.state:
                    message_body = message_body + '\n' +_('State %s -> %s') % (self._origin.state,self.state)
            
                thread_pool = self.env['mail.thread']
                mess_id = self.repositor_id.user_id.message_post(
                message_type="notification",
                subtype="mt_comment",
                subject = "Changes at route period point",
                body= message_body
                )





"""
    @api.multi
    @api.model
    def read_group(self):
        def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True):
        res = super(your_class, self).read_group(cr, uid, domain, fields, groupby, offset, limit=limit, context=context, orderby=orderby, lazy=lazy)
        if 'duration' in fields:
            for line in res:
                if '__domain' in line:
                    lines = self.search(cr, uid, line['__domain'], context=context)
                    pending_value = 0.0
                    for current_account in self.browse(cr, uid, lines, context=context):
                        pending_value += current_account.amount_pending
                    line['amount_pending'] = pending_value
        if 'amount_payed' in fields:
            for line in res:
                if '__domain' in line:
                    lines = self.search(cr, uid, line['__domain'], context=context)
                    payed_value = 0.0
                    for current_account in self.browse(cr, uid, lines, context=context):
                        payed_value += current_account.amount_payed
                    line['amount_payed'] = payed_value
        return res
"""