import { _converse, api, converse } from '@converse/headless';
import { CustomElement } from 'shared/components/element.js';
import { __ } from 'i18n';
import tplChatboxHead from './templates/chat-head.js';
import 'shared/modals/user-details.js';

import './styles/chat-head.scss';

const { Strophe } = converse.env;

export default class ChatHeading extends CustomElement {
    constructor() {
        super();
        this.jid = null;
    }

    static get properties() {
        return {
            jid: { type: String },
        };
    }

    initialize() {
        const { chatboxes } = _converse.state;
        this.model = chatboxes.get(this.jid);
        this.listenTo(this.model, 'change:status', () => this.requestUpdate());
        this.listenTo(this.model, 'vcard:add', () => this.requestUpdate());
        this.listenTo(this.model, 'vcard:change', () => this.requestUpdate());
        if (this.model.contact) {
            this.listenTo(this.model.contact, 'destroy', () => this.requestUpdate());
        }
        this.model.rosterContactAdded?.then(() => {
            this.listenTo(this.model.contact, 'change:nickname', () => this.requestUpdate());
            this.requestUpdate();
        });
        this.requestUpdate();
    }

    render() {
        return tplChatboxHead(this);
    }

    /**
     * @param {Event} ev
     */
    showUserDetailsModal(ev) {
        ev.preventDefault();
        if (this.model?.contact instanceof _converse.exports.Profile) {
            api.modal.show('converse-profile-modal', { model: this.model }, ev);
        } else {
            api.modal.show('converse-user-details-modal', { model: this.model }, ev);
        }
    }

    /**
     * @param {Event} ev
     */
    close(ev) {
        ev.preventDefault();
        this.model.close();
    }

    /**
     * Returns a list of objects which represent buttons for the chat's header.
     * @emits _converse#getHeadingButtons
     * @returns {Promise<Array.<import('./types').HeadingButtonAttributes>>}
     */
    async getHeadingButtons() {
        const buttons = [
            /** @type {import('./types').HeadingButtonAttributes} */
            {
                a_class: 'show-user-details-modal',
                handler: /** @param {Event} ev */ (ev) => this.showUserDetailsModal(ev),
                i18n_text: __('Details'),
                i18n_title: __('See more information about this person'),
                icon_class: 'fa-id-card',
                name: 'details',
                standalone: false,
            },
        ];

        const domain = _converse.session.get('domain');
        if (domain && (await api.disco.supports(Strophe.NS.BLOCKING, domain))) {
            const blocklist = await api.blocklist.get();
            if (blocklist.get(this.model.get('jid'))) {
                buttons.push({
                    a_class: 'unblock-user',
                    handler: /** @param {Event} ev */ async (ev) => {
                        ev.preventDefault();
                        const result = await api.confirm(__('Unblock user'), [
                            __('Are you sure you want to unblock this user?'),
                        ]);
                        if (result) {
                            api.blocklist.remove(this.model.get('jid'));
                        }
                    },
                    i18n_text: __('Unblock this user'),
                    i18n_title: __('Allow this user to send you messages'),
                    icon_class: 'fa-check',
                    name: 'unblock',
                    standalone: false,
                });
            } else {
                buttons.push({
                    a_class: 'block-user',
                    handler: /** @param {Event} ev */ async (ev) => {
                        ev.preventDefault();
                        const result = await api.confirm(__('Block user'), [
                            __(
                                'Are you sure you want to prevent %1$s from contacting you further?',
                                this.model.getDisplayName()
                            ),
                        ]);
                        if (result) {
                            const jid = this.model.get('jid');
                            api.blocklist.add(jid);
                            api.contacts.remove(jid, true);
                            this.model.close();
                        }
                    },
                    i18n_text: __('Block this user'),
                    i18n_title: __('Prevent this user from sending you any further messages'),
                    icon_class: 'fa-trash',
                    name: 'block',
                    standalone: false,
                });
            }
        }

        if (!api.settings.get('singleton')) {
            buttons.push({
                a_class: 'close-chatbox-button',
                handler: /** @param {Event} ev */ (ev) => this.close(ev),
                i18n_text: __('Close'),
                i18n_title: __('Close and end this conversation'),
                icon_class: 'fa-times',
                name: 'close',
                standalone: api.settings.get('view_mode') === 'overlayed',
            });
        }
        const { chatboxviews } = _converse.state;
        const el = chatboxviews.get(this.getAttribute('jid'));
        if (el) {
            /**
             * *Hook* which allows plugins to add more buttons to a chat's heading.
             *
             * Note: This hook is fired for both 1 on 1 chats and groupchats.
             * If you only care about one, you need to add a check in your code.
             *
             * @event _converse#getHeadingButtons
             * @param { HTMLElement } el
             *      The `converse-chat` (or `converse-muc`) DOM element that represents the chat
             * @param { Array.<import('./types').HeadingButtonAttributes> }
             *      An array of the existing buttons. New buttons may be added,
             *      and existing ones removed or modified.
             * @example
             *  api.listen.on('getHeadingButtons', (el, buttons) => {
             *      buttons.push({
             *          'i18n_title': __('Foo'),
             *          'i18n_text': __('Foo Bar'),
             *          'handler': ev => alert('Foo!'),
             *          'a_class': 'toggle-foo',
             *          'icon_class': 'fa-foo',
             *          'name': 'foo'
             *      });
             *      return buttons;
             *  });
             */
            return _converse.api.hook('getHeadingButtons', el, buttons);
        } else {
            return buttons; // Happens during tests
        }
    }
}

api.elements.define('converse-chat-heading', ChatHeading);
