/** @odoo-module **/

import { registerModel } from '@mail/model/model_core';
import { attr, many, one } from '@mail/model/model_field';
import { clear, insert, link, unlink } from '@mail/model/model_field_command';

registerModel({
    name: 'Follower',
    modelMethods: {
        /**
         * @param {Object} data
         * @returns {Object}
         */
        convertData(data) {
            const data2 = {};
            if ('id' in data) {
                data2.id = data.id;
            }
            if ('is_active' in data) {
                data2.isActive = data.is_active;
            }
            if ('partner_id' in data) {
                if (!data.partner_id) {
                    data2.partner = clear();
                } else {
                    const partnerData = {
                        display_name: data.display_name,
                        email: data.email,
                        id: data.partner_id,
                        name: data.name,
                    };
                    data2.partner = insert(partnerData);
                }
            }
            if (data.partner) {
                data2.partner = data.partner;
            }
            return data2;
        },
    },
    recordMethods: {
        /**
         *  Close subtypes dialog
         */
        closeSubtypes() {
            this.update({ followerSubtypeListDialog: clear() });
        },
        /**
         * Opens the most appropriate view that is a profile for this follower.
         */
        async openProfile() {
            return this.partner.openProfile();
        },
        /**
         * Remove this follower from its related thread.
         */
        async remove() {
            const partner_ids = [];
            partner_ids.push(this.partner.id);
            const followedThread = this.followedThread;
            await this.messaging.rpc({
                model: this.followedThread.model,
                method: 'message_unsubscribe',
                args: [[this.followedThread.id], partner_ids]
            });
            if (followedThread.exists()) {
                followedThread.fetchData(['suggestedRecipients']);
            }
            if (!this.exists()) {
                return;
            }
            this.delete();
        },
        /**
         * @param {FollowerSubtype} subtype
         */
        selectSubtype(subtype) {
            if (!this.selectedSubtypes.includes(subtype)) {
                this.update({ selectedSubtypes: link(subtype) });
            }
        },
        /**
         * Show (editable) list of subtypes of this follower.
         */
        async showSubtypes() {
            const subtypesData = await this.messaging.rpc({
                route: '/mail/read_subscription_data',
                params: { follower_id: this.id },
            });
            if (!this.exists()) {
                return;
            }
            this.update({ subtypes: clear() });
            for (const data of subtypesData) {
                const subtype = this.messaging.models['FollowerSubtype'].insert(
                    this.messaging.models['FollowerSubtype'].convertData(data)
                );
                this.update({ subtypes: link(subtype) });
                if (data.followed) {
                    this.update({ selectedSubtypes: link(subtype) });
                } else {
                    this.update({ selectedSubtypes: unlink(subtype) });
                }
            }
            this.update({ followerSubtypeListDialog: {} });
        },
        /**
         * @param {FollowerSubtype} subtype
         */
        unselectSubtype(subtype) {
            if (this.selectedSubtypes.includes(subtype)) {
                this.update({ selectedSubtypes: unlink(subtype) });
            }
        },
        /**
         * Update server-side subscription of subtypes of this follower.
         */
        async updateSubtypes() {
            if (this.selectedSubtypes.length === 0) {
                this.remove();
            } else {
                const kwargs = {
                    subtype_ids: this.selectedSubtypes.map(subtype => subtype.id),
                };
                if (this.partner) {
                    kwargs.partner_ids = [this.partner.id];
                }
                await this.messaging.rpc({
                    model: this.followedThread.model,
                    method: 'message_subscribe',
                    args: [[this.followedThread.id]],
                    kwargs,
                });
                if (!this.exists()) {
                    return;
                }
                this.messaging.notify({
                    type: 'success',
                    message: this.env._t("The subscription preferences were successfully applied."),
                });
            }
            this.closeSubtypes();
        },
    },
    fields: {
        followedThread: one('Thread', {
            inverse: 'followers',
        }),
        followedThreadAsFollowerOfCurrentPartner: one('Thread', {
            compute() {
                if (!this.followedThread) {
                    return clear();
                }
                if (!this.messaging.currentPartner) {
                    return clear();
                }
                if (this.partner === this.messaging.currentPartner) {
                    return this.followedThread;
                }
                return clear();
            },
            inverse: 'followerOfCurrentPartner',
        }),
        followerSubtypeListDialog: one('Dialog', {
            inverse: 'followerOwnerAsSubtypeList',
        }),
        followerViews: many('FollowerView', {
            inverse: 'follower',
        }),
        id: attr({
            identifying: true,
        }),
        isActive: attr({
            default: true,
        }),
        /**
         * States whether the follower's subtypes are editable by current user.
         */
        isEditable: attr({
            compute() {
                const hasWriteAccess = this.followedThread ? this.followedThread.hasWriteAccess : false;
                const hasReadAccess = this.followedThread ? this.followedThread.hasReadAccess : false;
                return this.messaging.currentPartner === this.partner ? hasReadAccess : hasWriteAccess;
            },
        }),
        partner: one('Partner', {
            required: true,
        }),
        selectedSubtypes: many('FollowerSubtype'),
        subtypes: many('FollowerSubtype'),
    },
});
