#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
from trytond.model import ModelView, ModelSQL, fields
from trytond.pyson import Not, Equal, Eval
from trytond.transaction import Transaction


class Purchase(ModelSQL, ModelView):
    _name = "purchase.purchase"

    def __init__(self):
        super(Purchase, self).__init__()
        self._error_messages.update({
            'analytic_account_required': 'Analytic account is required ' \
                    'on line "%s" (%d)!',
            })

    def check_for_quotation(self, purchase_id):
        account_selection_obj = self.pool.get(
                'analytic_account.account.selection')
        purchase_line_obj = self.pool.get('purchase.line')

        res = super(Purchase, self).check_for_quotation(purchase_id)

        purchase = self.browse(purchase_id)
        if not account_selection_obj.check_root(
                [x.analytic_accounts.id for x in purchase.lines
                    if x.analytic_accounts.id]):
            for line in purchase.lines:
                if line.type != 'line':
                    continue
                if not account_selection_obj.check_root(
                        [line.analytic_accounts.id]):
                    self.raise_user_error('analytic_account_required',
                            (line.rec_name, line.id))
        return res

Purchase()


class PurchaseLine(ModelSQL, ModelView):
    _name = 'purchase.line'

    analytic_accounts = fields.Many2One('analytic_account.account.selection',
            'Analytic Accounts',
            states={
                'invisible': Not(Equal(Eval('type'), 'line')),
            })

    def _view_look_dom_arch(self, tree, type):
        analytic_account_obj = self.pool.get('analytic_account.account')
        analytic_account_obj.convert_view(tree)
        arch, fields = super(PurchaseLine, self)._view_look_dom_arch(tree, type)
        return arch, fields

    def fields_get(self, fields_names=None):
        analytic_account_obj = self.pool.get('analytic_account.account')

        res = super(PurchaseLine, self).fields_get(fields_names)

        analytic_accounts_field = super(PurchaseLine, self).fields_get(
                ['analytic_accounts'])['analytic_accounts']

        res.update(analytic_account_obj.analytic_accounts_fields_get(
            analytic_accounts_field, fields_names))
        return res

    def default_get(self, fields, with_rec_name=True):
        fields = [x for x in fields if not x.startswith('analytic_account_')]
        return super(PurchaseLine, self).default_get(fields,
            with_rec_name=with_rec_name)

    def read(self, ids, fields_names=None):
        selection_obj = self.pool.get('analytic_account.account.selection')

        int_id = False
        if isinstance(ids, (int, long)):
            int_id = True
            ids = [ids]

        if fields_names:
            fields_names2 = [x for x in fields_names
                    if not x.startswith('analytic_account_')]
        else:
            fields_names2 = fields_names

        res = super(PurchaseLine, self).read(ids, fields_names=fields_names2)

        if not fields_names:
            fields_names = list(set(self._columns.keys() \
                    + self._inherit_fields.keys()))

        root_ids = []
        for field in fields_names:
            if field.startswith('analytic_account_') and '.' not in field:
                root_ids.append(int(field[len('analytic_account_'):]))
        if root_ids:
            id2record = {}
            for record in res:
                id2record[record['id']] = record
            lines = self.browse(ids)
            for line in lines:
                for root_id in root_ids:
                    id2record[line.id]['analytic_account_' \
                            + str(root_id)] = False
                if line.type != 'line':
                    continue
                if not line.analytic_accounts:
                    continue
                for account in line.analytic_accounts.accounts:
                    if account.root.id in root_ids:
                        id2record[line.id]['analytic_account_' \
                                + str(account.root.id)] = account.id
                        for field in fields_names:
                            if field.startswith('analytic_account_' + \
                                    str(account.root.id) + '.'):
                                ham, field2 = field.split('.', 1)
                                id2record[line.id][field] = account[field2]
        if int_id:
            return res[0]
        return res

    def create(self, vals):
        selection_obj = self.pool.get('analytic_account.account.selection')
        vals = vals.copy()
        selection_vals = {}
        for field in vals.keys():
            if field.startswith('analytic_account_'):
                if vals[field]:
                    selection_vals.setdefault('accounts', [])
                    selection_vals['accounts'].append(('add', vals[field]))
                del vals[field]
        if vals.get('analytic_accounts'):
            selection_obj.write(vals['analytic_accounts'], selection_vals)
        elif vals.get('type', 'line') == 'line':
            selection_id = selection_obj.create(selection_vals)
            vals['analytic_accounts'] = selection_id
        return super(PurchaseLine, self).create(vals)

    def write(self, ids, vals):
        selection_obj = self.pool.get('analytic_account.account.selection')
        vals = vals.copy()
        if isinstance(ids, (int, long)):
            ids = [ids]
        selection_vals = {}
        for field in vals.keys():
            if field.startswith('analytic_account_'):
                root_id = int(field[len('analytic_account_'):])
                selection_vals[root_id] = vals[field]
                del vals[field]
        if selection_vals:
            lines = self.browse(ids)
            for line in lines:
                if line.type != 'line':
                    continue
                accounts = []
                if not line.analytic_accounts:
                    # Create missing selection
                    with Transaction().set_user(0):
                        selection_id = selection_obj.create({})
                    self.write(line.id, {
                        'analytic_accounts': selection_id,
                        })
                    line = self.browse(line.id)
                for account in line.analytic_accounts.accounts:
                    if account.root.id in selection_vals:
                        value = selection_vals[account.root.id]
                        if value:
                            accounts.append(value)
                    else:
                        accounts.append(account.id)
                for account_id in selection_vals.values():
                    if account_id \
                            and account_id not in accounts:
                        accounts.append(account_id)
                selection_obj.write(line.analytic_accounts.id, {
                    'accounts': [('set', accounts)],
                    })
        return super(PurchaseLine, self).write(ids, vals)

    def delete(self, ids):
        selection_obj = self.pool.get('analytic_account.account.selection')

        if isinstance(ids, (int, long)):
            ids = [ids]
        selection_ids = []
        lines = self.browse(ids)
        for line in lines:
            if line.analytic_accounts:
                selection_ids.append(line.analytic_accounts.id)

        res = super(PurchaseLine, self).delete(ids)
        selection_obj.delete(selection_ids)
        return res

    def copy(self, ids, default=None):
        selection_obj = self.pool.get('analytic_account.account.selection')

        new_ids = super(PurchaseLine, self).copy(ids, default=default)

        int_id = False
        if isinstance(new_ids, (int, long)):
            int_id = True
            new_ids = [new_ids]

        for line in self.browse(new_ids):
            if line.analytic_accounts:
                selection_id = selection_obj.copy(line.analytic_accounts.id)
                self.write(line.id, {
                    'analytic_accounts': selection_id,
                    })

        if int_id:
            return new_ids[0]
        return new_ids

    def get_invoice_line(self, line):
        account_selection_obj = self.pool.get('analytic_account.account.selection')

        res = super(PurchaseLine, self).get_invoice_line(line)
        if not res:
            return res

        selection_id = False
        if line.analytic_accounts:
            selection_id = account_selection_obj.copy(line.analytic_accounts.id)
        for vals in res:
            vals['analytic_accounts'] = selection_id
        return res

PurchaseLine()


class Account(ModelSQL, ModelView):
    _name = 'analytic_account.account'

    def delete(self, ids):
        purchase_line_obj = self.pool.get('purchase.line')
        res = super(Account, self).delete(ids)
        # Restart the cache on the fields_view_get method of purchase.line
        purchase_line_obj.fields_view_get.reset()
        return res

    def create(self, vals):
        purchase_line_obj = self.pool.get('purchase.line')
        res = super(Account, self).create(vals)
        # Restart the cache on the fields_view_get method of purchase.line
        purchase_line_obj.fields_view_get.reset()
        return res

    def write(self, ids, vals):
        purchase_line_obj = self.pool.get('purchase.line')
        res = super(Account, self).write(ids, vals)
        # Restart the cache on the fields_view_get method of purchase.line
        purchase_line_obj.fields_view_get.reset()
        return res

Account()
