# 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 itertools import chain

from sql import With

from trytond.model import (
    DeactivableMixin, ModelSQL, ModelView, Unique, fields, tree)
from trytond.pool import Pool


class MenuMany2Many(fields.Many2Many):

    def get(self, ids, model, name, values=None):
        Menu = self.get_target()
        res = super().get(ids, model, name,
                values=values)
        menu_ids = list(set(chain(*res.values())))
        menu_ids = list(map(int, Menu.search([
                        ('id', 'in', menu_ids),
                        ])))
        for group_id, ids in res.items():
            res[group_id] = tuple(id_ for id_ in ids if id_ in menu_ids)
        return res


class Group(DeactivableMixin, tree(), ModelSQL, ModelView):
    __name__ = "res.group"
    name = fields.Char('Name', required=True, translate=True)
    users = fields.Many2Many('res.user-res.group', 'group', 'user', 'Users')
    parent = fields.Many2One(
        'res.group', "Parent",
        help="The group to inherit accesses from.")
    model_access = fields.One2Many('ir.model.access', 'group',
       'Access Model')
    field_access = fields.One2Many('ir.model.field.access', 'group',
        'Access Field')
    buttons = fields.Many2Many(
        'ir.model.button-res.group', 'group', 'button', "Buttons")
    rule_groups = fields.Many2Many('ir.rule.group-res.group',
       'group', 'rule_group', 'Rules',
       domain=[('global_p', '!=', True), ('default_p', '!=', True)])
    menu_access = MenuMany2Many('ir.ui.menu-res.group',
       'group', 'menu', 'Access Menu')

    @classmethod
    def __setup__(cls):
        super().__setup__()
        table = cls.__table__()
        cls._sql_constraints += [
            ('name_uniq', Unique(table, table.name),
                'The name of the group must be unique!')
        ]
        cls._order.insert(0, ('name', 'ASC'))

    @classmethod
    def on_modification(cls, mode, groups, field_names=None):
        pool = Pool()
        User = pool.get('res.user')
        super().on_modification(mode, groups, field_names=field_names)
        User._get_groups_cache.clear()

    @classmethod
    def copy(cls, groups, default=None):
        if default is None:
            default = {}
        default = default.copy()

        new_groups = []
        for group in groups:
            i = 1
            while True:
                name = '%s (%d)' % (group.name, i)
                if not cls.search([('name', '=', name)], order=[]):
                    break
                i += 1
            default['name'] = name
            new_groups.extend(super().copy([group], default=default))
        return new_groups

    @classmethod
    def group_parent_all_cte(cls):
        group = cls.__table__()
        parents = With('id', 'parent', recursive=True)
        parents.query = group.select(group.id, group.parent)
        parents.query |= group.select(group.id, group.id)
        parents.query |= (group
            .join(parents, condition=group.parent == parents.id)
            .select(group.id, parents.parent))
        return parents
