import {inject as injectService} from '@ember/service';
import {scheduleOnce, throttle} from '@ember/runloop';
import {htmlSafe} from '@ember/string';
import {isEmpty, isNone} from '@ember/utils';

import FWHeader from '@bennerinformatics/ember-fw/components/fw-header';
import {sortBy} from '@bennerinformatics/ember-fw/utils/computed';
import layout from '@bennerinformatics/ember-fw-gc/templates/components/fw-header';

/**
 * Page Header Component. This extends [Ember FW's FwHeader](https://linformatics.bitbucket.io/docs/addons/client-api/ember-fw/classes/FwHeader.html).
 * In addition to the logo and App Name rendered by Ember FW's FwHeader, Ember FW GC also adds information about the user, such as the app switcher,
 * current department and dropdown on the right side of the header. It also is responsible for calling the following modals: about, app-switch, and change-password.
 *
 * It is called in an identical way as Ember FW's `FwHeader`:
 * ```handlebars
 * <FwHeader />
 * ```
 *
 * There is no configuration for this component, so everything is documented as private.
 *
 * @public
 * @class FwHeaderGc
 * @extends FwHeader
 * @module Components
 */
export default FWHeader.extend({
    layout,

    // deprecated by currentUser service
    user: null,
    currentDepartment: null,
    app: null,

    // department switcher
    departments: null,
    sortedDepartments: sortBy('departments', 'name'),
    // label for the switch department dropdown
    switchDepartmentLabel: htmlSafe('<i class="fa-solid fa-arrow-right-arrow-left" style="margin-right: 2px;"></i>&nbsp;Switch Departments'),

    /**
     * Deprecated. This property actually does nothing and should be deleted from your FwHeader
     *
     * @public
     * @property showAboutLink
     * @type {Boolean}
     * @deprecated
     */
    showAboutLink: false,

    /**
     * Flags for whether modals are shown or not. Contains: about, apps, and change booleans within it.
     * @property modals
     * @type {Object}
     * @private
     */
    modals: {
        about: false,
        apps: false,
        change: false
    },

    /**
     * Whether or not the dropdown is currently shown. Internal.
     * @property showDropdown
     * @type {Boolean}
     * @private
     */
    showDropdown: false,

    /**
     * Whether or not the logged in user needs a password change
     *
     * @private
     * @property needSecureChangePassword
     * @type {Boolean}
     */
    needSecureChangePassword: false,

    // Services
    currentUser: injectService(),
    notifications: injectService(),
    session: injectService(),
    config: injectService(),
    ajax: injectService(),

    // Hooks to the currentUser service to open the change password modal when needed
    init() {
        this._super(...arguments);

        this.get('currentUser').on('change-password', this, function (needSecure) {
            this.send('toggleChangeModal', needSecure);
        });
    },

    didReceiveAttrs() {
        this._super(...arguments);
        if (this.get('session.isAuthenticated')) {
            this._loadDepartment();
        } else {
            this.get('currentUser').on('login', this, this._loadDepartment);
        }
    },

    /** Called on load to load the current visible department */
    _loadDepartment() {
        let currentDept = this.get('currentUser.currentDept');
        // department may be empty if the user has no roles
        if (isEmpty(currentDept)) {
            return;
        }
        let departmentUrl = this.get('config').formGCUrl('departments', currentDept);

        this.get('ajax').request(departmentUrl).then(({department}) => {
            scheduleOnce('afterRender', () => {
                this.set('currentDepartment', department.name);
            });
        });
    },

    /** Called when the menu is clicked to load all available departments */
    _loadDepartments() {
        if (isNone(this.get('departments'))) {
            this.get('ajax').request(this.get('config').formGCUrl('departments', {limit: 'current'})).then(({departments}) => {
                this.set('departments', departments);
            });
        }
    },

    /** Toggles the dropdown value */
    toggleDropdown(value) {
        throttle(this, 'set', 'showDropdown', !!value, 100);
    },

    actions: {
        /** Logs the user out of FW */
        logout() {
            this.get('session').invalidate();
        },

        /** Reloads the user's permissions */
        reload() {
            this.get('currentUser').reload().catch(() => {
                this.get('notifications').showError('Reload failed!', 'global');
            });
        },

        /** Sets the dropdown to open or closed */
        toggleDropdown(value) {
            this.toggleDropdown(value);
            if (value) {
                this._loadDepartments();
            }
        },

        /** Shows the given modal */
        showModal(name) {
            this.set(`modals.${name}`, true);
            this.toggleDropdown(false);
        },

        /** Shows the apps modal */
        toggleAppsModal() {
            if (this.get('session.isAuthenticated')) {
                this.toggleProperty('modals.apps');
            }
            this.toggleDropdown(false);
        },

        /** Shows the change password modall */
        toggleChangeModal(needSecure = false) {
            this.toggleProperty('modals.change');
            this.set('needSecureChangePassword', needSecure);
        },

        /** Switches the user's current department */
        changeDepartment(department) {
            if (!this.get('currentUser').checkDepartment(department.id)) {
                this.get('currentUser').changeDepartment(department.id).then(() => {
                    window.location.replace(this.get('config.url'));
                }).catch(() => {
                    this.get('notifications').showError('Failed to switch departments!', 'global');
                });
            }
        }
    }
});