from patch.include import *
from common.models.cmf_active_entity import CmfActiveEntity
from tqdm import tqdm


@app_context(commit=True)
def patch():
    set_count = 0

    def set_object_policy(obj_id_, policy_anonymous_):
        nonlocal set_count
        set_count += 1
        obj_fields = cmfutil.get_model_by_id(obj_id_)().save_preload_fields()
        obj = cmfutil.get_obj_by_id(obj_id_, fields=obj_fields)  # type: CmfActiveEntity
        # будем ломать прогресбар
        print(f'Set {obj} anonymous policy to {policy_anonymous_}')
        obj.perm_policy_anonymous = policy_anonymous_
        obj.save()  # может быть тяжёлым.

    ae_dict = {}
    print('Load data')
    for model in tqdm(CmfActiveEntity.iter_subclasses()):
        for obj_data in model.slist(
                # filter=['is_public', '=', True],
                fields=['--', 'id', 'perm_parent_id', 'is_public*', 'perm_policy_anonymous']):
            ae_dict[obj_data.id] = obj_data

    print('Process data')
    for obj_id, obj_data in tqdm(ae_dict.items()):
        if obj_data.perm_policy_anonymous != 'default':
            continue
        parent_data = ae_dict.get(obj_data.perm_parent_id)
        if not obj_data.is_public:
            # Если paren.is_public, то ставим политику deny
            if parent_data and parent_data.is_public:
                set_object_policy(obj_id, 'deny')
        else:
            if parent_data \
                    and (obj_data.is_public, obj_data.is_public_editable, obj_data.is_public_comments) \
                    == (parent_data.is_public, parent_data.is_public_editable, parent_data.is_public_comments):
                continue  # use default inheritance
            policy_anonymous = 'read'
            if obj_data.is_public_editable:
                policy_anonymous = 'full'
            elif obj_data.is_public_comments:
                policy_anonymous = 'comment'
            set_object_policy(obj_id, policy_anonymous)
    print(f'Patched {set_count}/{len(ae_dict)}')


if __name__ == "__main__":
    patch()
