#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 __future__ import with_statement
import copy
from trytond.model import ModelView, ModelSQL, fields
from trytond.wizard import Wizard
from trytond.report import Report
from trytond.pyson import Eval, If, In, Get
from trytond.transaction import Transaction


class Company(ModelSQL, ModelView):
    'Company'
    _name = 'company.company'
    _description = __doc__
    _inherits = {'party.party': 'party'}

    party = fields.Many2One('party.party', 'Party', required=True,
            ondelete='CASCADE')
    parent = fields.Many2One('company.company', 'Parent')
    childs = fields.One2Many('company.company', 'parent', 'Children')
    header = fields.Text('Header')
    footer = fields.Text('Footer')
    currency = fields.Many2One('currency.currency', 'Currency', required=True)
    employees = fields.One2Many('company.employee', 'company', 'Employees')

    def __init__(self):
        super(Company, self).__init__()
        self._constraints += [
            ('check_recursion', 'recursive_companies'),
        ]
        self._error_messages.update({
            'recursive_companies': 'You can not create recursive companies!',
        })

    def copy(self, ids, default=None):
        party_obj = self.pool.get('party.party')

        int_id = False
        if isinstance(ids, (int, long)):
            int_id = True
            ids = [ids]
        if default is None:
            default = {}
        default = default.copy()
        new_ids = []
        for company in self.browse(ids):
            default['party'] = party_obj.copy(company.party.id)
            new_id = super(Company, self).copy(company.id, default=default)
            new_ids.append(new_id)

        if int_id:
            return new_ids[0]
        return new_ids

    def write(self, ids, vals):
        res = super(Company, self).write(ids, vals)
        # Restart the cache on the domain_get method
        self.pool.get('ir.rule').domain_get.reset()
        return res

Company()


class Employee(ModelSQL, ModelView):
    'Employee'
    _name = 'company.employee'
    _description = __doc__
    _inherits = {'party.party': 'party'}

    party = fields.Many2One('party.party', 'Party', required=True)
    company = fields.Many2One('company.company', 'Company', required=True)

Employee()


class User(ModelSQL, ModelView):
    _name = 'res.user'
    main_company = fields.Many2One('company.company', 'Main Company',
            on_change=['main_company'])
    company = fields.Many2One('company.company', 'Current Company',
            domain=[('parent', 'child_of', [Eval('main_company')], 'parent')],
            depends=['main_company'])
    companies = fields.Function(fields.One2Many('company.company', None,
        'Current Companies'), 'get_companies')
    employee = fields.Many2One('company.employee', 'Employee',
            domain=[('company', 'child_of', [Eval('main_company')], 'parent')])

    def __init__(self):
        super(User, self).__init__()
        self._context_fields.insert(0, 'company')
        self._constraints += [
                ('check_company', 'child_company'),
                ]
        self._error_messages.update({
            'child_company': 'You can not set a company that is not ' \
                    'a child of your main company!',
        })

    def default_main_company(self):
        return Transaction().context.get('company') or False

    def default_company(self):
        return self.default_main_company()

    def get_companies(self, ids, name):
        company_obj = self.pool.get('company.company')
        res = {}
        company_childs = {}
        for user in self.browse(ids):
            res[user.id] = []
            company_id = False
            if user.company:
                company_id = user.company.id
            elif user.main_company:
                company_id = user.main_company.id
            if company_id:
                if company_id in company_childs:
                    company_ids = company_childs[company_id]
                else:
                    company_ids = company_obj.search([
                        ('parent', 'child_of', [company_id]),
                        ])
                    company_childs[company_id] = company_ids
                if company_ids:
                    res[user.id].extend(company_ids)
        return res

    def get_status_bar(self, ids, name):
        res = super(User, self).get_status_bar(ids, name)
        for user in self.browse(ids):
            if user.company:
                res[user.id] += ' ' + user.company.name
        return res

    def on_change_main_company(self, vals):
        return {'company': vals.get('main_company', False)}

    def check_company(self, ids):
        company_obj = self.pool.get('company.company')
        for user in self.browse(ids):
            if user.main_company:
                companies = company_obj.search([
                    ('parent', 'child_of', [user.main_company.id]),
                    ])
                if user.company.id and (user.company.id not in companies):
                    return False
            elif user.company:
                return False
        return True

    def _get_preferences(self, user, context_only=False):
        res = super(User, self)._get_preferences(user, 
                context_only=context_only)
        if not context_only:
            res['main_company'] = user.main_company.id
        if user.employee:
            res['employee'] = user.employee.id
        return res

    def get_preferences_fields_view(self):
        company_obj = self.pool.get('company.company')

        user = self.browse(Transaction().user)

        res = super(User, self).get_preferences_fields_view()
        res = copy.deepcopy(res)
        return res

User()


class Property(ModelSQL, ModelView):
    _name = 'ir.property'
    company = fields.Many2One('company.company', 'Company',
            domain=[
                ('id', If(In('company', Eval('context', {})), '=', '!='),
                    Get(Eval('context', {}), 'company', 0)),
            ])

    def _set_values(self, name, model, res_id, val, field_id):
        user_obj = self.pool.get('res.user')
        user = user_obj.browse(Transaction().user)
        res = super(Property, self)._set_values(name, model, res_id, val, 
                field_id)
        if user:
            res['company'] = user.company.id
        return res

    def search(self, domain, offset=0, limit=None, order=None, count=False):
        if Transaction().user == 0:
            domain = ['AND', domain[:], ('company', '=', False)]
        return super(Property, self).search(domain, offset=offset,
                limit=limit, order=order, count=count)

Property()


class Sequence(ModelSQL, ModelView):
    _name = 'ir.sequence'
    company = fields.Many2One('company.company', 'Company',
            domain=[
                ('id', If(In('company', Eval('context', {})), '=', '!='),
                    Get(Eval('context', {}), 'company', 0)),
            ])

    def __init__(self):
        super(Sequence, self).__init__()
        self._order.insert(0, ('company', 'ASC'))

    def default_company(self):
        return Transaction().context.get('company') or False

Sequence()


class SequenceStrict(Sequence):
    _name = 'ir.sequence.strict'

SequenceStrict()


class CompanyConfigInit(ModelView):
    'Company Config Init'
    _name = 'company.company.config.init'
    _description = __doc__

CompanyConfigInit()


class CompanyConfig(Wizard):
    'Configure companies'
    _name = 'company.company.config'
    states = {
        'init': {
            'result': {
                'type': 'form',
                'object': 'company.company.config.init',
                'state': [
                    ('end', 'Cancel', 'tryton-cancel'),
                    ('company', 'Ok', 'tryton-ok', True),
                ],
            },
        },
        'company': {
            'result': {
                'type': 'form',
                'object': 'company.company',
                'state': [
                    ('end', 'Cancel', 'tryton-cancel'),
                    ('add', 'Add', 'tryton-ok', True),
                ],
            },
        },
        'add': {
            'result': {
                'type': 'action',
                'action': '_add',
                'state': 'end',
            },
        },
    }

    def _add(self, data):
        company_obj = self.pool.get('company.company')
        user_obj = self.pool.get('res.user')

        company_id = company_obj.create(data['form'])
        user_ids = user_obj.search([
            ('main_company', '=', False),
            ])
        user_obj.write(user_ids, {
            'main_company': company_id,
            'company': company_id,
            })
        return {}

CompanyConfig()


class CompanyReport(Report):

    def parse(self, report, objects, datas, localcontext=None):
        user = self.pool.get('res.user').browse(Transaction().user)
        if localcontext is None:
            localcontext = {}
        localcontext['company'] = user.company
        return super(CompanyReport, self).parse(report, objects, datas,
                localcontext=localcontext)


class LetterReport(CompanyReport):
    _name = 'party.letter'

LetterReport()
