import { html } from 'lit';
import { _converse, api, log, Model } from '@converse/headless';
import { __ } from 'i18n';
import BaseModal from 'plugins/modal/modal.js';
import { compressImage } from 'utils/file.js';
import '../password-reset.js';
import { modal_close_button } from 'plugins/modal/templates/buttons.js';
import tplLogoutButton from '../templates/logout_button.js';
import tplProfileModal from '../templates/profile_modal.js';

import './styles/profile.scss';

export default class ProfileModal extends BaseModal {
    /**
     * @typedef {import('@converse/headless/types/plugins/vcard/types').VCardData} VCardData
     * @typedef {import("@converse/headless").Profile} Profile
     * @typedef {import("lit").TemplateResult} TemplateResult
     */

    static properties = {
        _submitting: { state: true },
        _show_clear_button: { type: Boolean, state: true },
        model: { type: Model },
        tab: { type: String },
    };

    /**
     * @param {Object} options
     */
    constructor(options) {
        super(options);
        this.tab = 'status';
        this._show_clear_button = false;
    }

    initialize() {
        super.initialize();
        this.listenTo(this.model, 'change', this.render);
        this.addEventListener(
            'shown.bs.modal',
            () => {
                /** @type {HTMLInputElement} */ (this.querySelector('input[name="status_message"]'))?.focus();
            },
            false
        );

        /**
         * Triggered when the _converse.ProfileModal has been created and initialized.
         * @event _converse#profileModalInitialized
         * @type {Profile}
         * @example _converse.api.listen.on('profileModalInitialized', status => { ... });
         */
        api.trigger('profileModalInitialized', this.model);
    }

    /**
     * @param {Map<string, boolean>} changed - A map of changed properties.
     */
    willUpdate(changed) {
        if (changed.has('model')) {
            this._show_clear_button = !!this.model.get('status_message');
        }
    }

    getModalTitle() {
        return __('Your Profile');
    }

    /**
     * @returns {TemplateResult}
     */
    renderModal() {
        return tplProfileModal(this);
    }

    /**
     * @returns {TemplateResult|String}
     */
    renderModalFooter() {
        return api.settings.get('allow_logout')
            ? html`<div class="modal-footer d-flex justify-content-between">
                  ${modal_close_button} ${tplLogoutButton(this)}
              </div>`
            : '';
    }

    /**
     * @param {VCardData} data
     */
    async setVCard(data) {
        const bare_jid = _converse.session.get('bare_jid');
        try {
            await api.vcard.set(bare_jid, data);
        } catch (err) {
            log.fatal(err);
            this.alert(
                [
                    __('Sorry, an error happened while trying to save your profile data.'),
                    __("You can check your browser's developer console for any error output."),
                ].join(' ')
            );
            return false;
        }
        return true;
    }

    /**
     * @param {SubmitEvent} ev
     */
    async onProfileFormSubmitted(ev) {
        ev.preventDefault();
        this._submitting = true;

        const form_data = new FormData(/** @type {HTMLFormElement} */ (ev.target));
        const image_file = /** @type {File} */ (form_data.get('avatar_image'));

        const data = /** @type {VCardData} */ ({
            fn: form_data.get('fn'),
            nickname: form_data.get('nickname'),
            role: form_data.get('role'),
            email: form_data.get('email'),
            url: form_data.get('url'),
        });

        if (image_file?.size) {
            const image_data = await compressImage(image_file);
            const reader = new FileReader();
            reader.onloadend = async () => {
                Object.assign(data, {
                    image: btoa(/** @type {string} */ (reader.result)),
                    image_type: image_file.type,
                });
                if (await this.setVCard(data)) {
                    this._submitting = false;
                    this.modal.hide();
                }
            };
            reader.readAsBinaryString(image_data);
        } else {
            Object.assign(data, {
                image: this.model.vcard.get('image'),
                image_type: this.model.vcard.get('image_type'),
            });
            if (await this.setVCard(data)) {
                this.modal.hide();
                api.toast.show('vcard-updated', { type: 'success', body: __('Profile updated successfully') });
            }
            this._submitting = false;
        }
    }

    /**
     * @param {SubmitEvent} ev
     */
    onStatusFormSubmitted(ev) {
        ev.preventDefault();
        const data = new FormData(/** @type {HTMLFormElement} */ (ev.target));
        let show, presence;
        const chat_status = data.get('chat_status');
        if (chat_status === 'online') {
            presence = 'online';
        } else {
            show = chat_status;
        }
        this.model.save({
            status_message: data.get('status_message'),
            presence,
            show,
        });
        this.alert(__('Status updated'), 'info');
    }

    /**
     * @param {MouseEvent} ev
     */
    clearStatusMessage(ev) {
        if (ev && ev.preventDefault) {
            ev.preventDefault();
        }
        this._show_clear_button = false;
        const roster_filter = /** @type {HTMLInputElement} */ (this.querySelector('input[name="status_message"]'));
        roster_filter.value = '';
    }

    /**
     * @param {MouseEvent} ev
     */
    async logOut(ev) {
        ev?.preventDefault();
        this.close();
        const result = await api.confirm(__('Confirm'), __('Are you sure you want to log out?'));
        if (result) {
            api.user.logout();
        }
    }
}

api.elements.define('converse-profile-modal', ProfileModal);
