/**
 * @class
 * @classdesc Implements and exports Filemanager mixin.
 * @version 01.02.000
 * @mixin
 * @extends {superClass}
 * 
 * @property {Object} fontObjHeader The font object of the header.
 * @property {Object} fontObjBody   The font object of the body.
 * @property {Object} fontObjTitle  The font object of the title.
 */
export const Filemanager = function (superClass) {
    return class extends superClass {

        /**
         * Creates an instance of Filemanager mixin.
         * @memberof Filemanager
         */
        constructor() {
            super();
            this.fontObjHeader = null;
            this.fontObjBody = null;
            this.fontObjTitle = null;
        }

        /**
         * Checks if it is possible to pause the queue in order to enable the "Pause" button in the progress dialog. 
         * @private
         * @param {Boolean} isactive If true, the queue is active.
         * @param {Number} count The number of commands left in the queue.
         * @returns {Boolean} Returns true if it is possible to pause the queue. Otherwise, it returns false.
         * @memberof Filemanager
         */
        _canPause(isactive, count) {
            if (this.isdesignmode) return true;
            if (isactive && count >= 2) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * Checks if the queue is currently paused in order to enable the "Continue" button in the progress dialog. 
         * @private
         * @param {Boolean} isactive If true, the queue is active.
         * @param {Number} count The number of commands left in the queue.
         * @param {Boolean} isRunning If true, the queue is running.
         * @returns {Boolean} Returns true if it is possible to continue the queue. Otherwise, it returns false.
         * @memberof Filemanager
         */
        _canContinue(isactive, count, isRunning) {
            if (this.isdesignmode) return true;
            if (!isactive && count >= 1 && !isRunning) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * Checks if it is possible to cancel a single command in the queue in order to enable the "Cancel" button in the progress dialog.
         * @private
         * @param {Boolean} isactive If true, the queue is active.
         * @param {Number} count The number of commands left in the queue.
         * @returns {Boolean} Returns true if it is possible to cancel a single command in the queue. Otherwise, it returns false.
         * @memberof Filemanager
         */
        _canCancel(isactive, count) {
            if (this.isdesignmode) return true;
            if (isactive && count >= 1) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * Checks if it is possible to cancel all commands in the queue in order to enable the "Cancel all" button in the progress dialog.
         * @private
         * @param {Boolean} isactive If true, the queue is active.
         * @param {Number} count The number of commands left in the queue.
         * @returns {Boolean} Returns true if it is possible to cancel all commands in the queue. Otherwise, it returns false.
         * @memberof Filemanager
         */
        _canCancelAll(isactive, count) {
            if (this.isdesignmode) return true;
            if (isactive && count >= 2) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * Sets the text in parameter for the property passed in parameter.
         * @private
         * @param {String} property Property
         * @param {String | Object | Undefined} text Text to be set.
         * @returns {Undefined} Undefined
         * @memberof Filemanager
         */
        _setPropertyText(property, text) {
            if (typeof property === 'string') {
                const propertyObj = property + 'Obj';
                if (text instanceof Object) {
                    this[propertyObj] = text;
                    this[property] = this.tmApi.getTextWithParameter(this[propertyObj]);
                } else if (typeof text === 'string') {
                    this[property] = text;
                } else if (text === undefined && this[propertyObj] instanceof Object) {
                    this[property] = this.tmApi.getTextWithParameter(this[propertyObj]);
                }
            }
        }

        /**
         * Returns the text object from controlsTextList passed in parameter.
         * @private
         * @param {String} [text=''] Text key in the control's text list.
         * @param {Array}  [param=[]] Parameter.
         * @param {Object} [textList=controlTextList] The object of control's text list.
         * @returns {Object} Text object
         * @memberof Filemanager
        */
        _getTextObj(text = '', param = [], textList = this.controlTextList) {
            return {
                text: text,
                textList: textList,
                param: param
            };
        }

        /**
         * A simple sort function to sort two strings alphebtically in ascending or descanding order. Case insensitive !
         * @private
         * @param {*} a The first string.
         * @param {*} b The second string.
         * @param {boolean} [ascending=true] If true, sorting is to be done in ascending order. Otherwise, in descanding order.
         * @returns {Number} Returns 0 if strings are identical - sorting is unnecessary. 
         * Returns 1 if the first and the second string are already sorted in specified order.
         * Returns -1 if the first and the second string are NOT sorted in specified order, they should be swept.
         * @memberof Filemanager
         */
        _sort(a, b, ascending = true) {
            const aa = a.toLowerCase();
            const bb = b.toLowerCase();
            if (ascending) {
                return aa < bb ? 1 : aa > bb ? -1 : 0;
            } else {
                return aa < bb ? -1 : aa > bb ? 1 : 0;
            }
        }

        /**
         * Opens an alert window with the title, message, status and style passed in parameter by calling the Window Manager API.
         * @private
         * @param {String} [message=''] Message that will be shown in the system alert window.
         * @param {String} [title=''] Title that will shown in the system alert window.
         * @param {Number} [status=0] Status.
         * @param {Object} [style=undefined] Style object describing the styling of the system window.
         * @returns {Boolean} True, if the window was opened.
         * @memberof Filemanager
         */
        _showAlert(message = '', title = '', status = 0, style = undefined) {
            this.systemWindowOpened = true;
            return this.wmApi.systemWindow_alert(message, title, status, style);
        }

        /**
        * Opens a confirm window with the title, message, status and style passed in parameter by calling the Window Manager API.
        * @private
        * @param {String} [message=''] Message that will be shown in the system confirm window.
        * @param {String} [title=''] Title that will shown in the system confirm window.
        * @param {Number} [status=0] Status.
        * @param {Object} [style=undefined] Style object describing the styling of the system window.
        * @returns {Boolean} True, if the window was opened.
        * @memberof Filemanager
        */
        _showConfirm(message = '', title = '', status = 0, style = undefined) {
            this.systemWindowOpened = true;
            return this.wmApi.systemWindow_confirm(message, title, status, style);
        }

        /**
         * Opens a prompt window with the title, message, status and style passed in parameter by calling the Window Manager API.
         * @private
         * @param {String} [message=''] Message that will be shown in the system prompt window.
         * @param {String} [title=''] Title that will shown in the system prompt window.
         * @param {Number} [status=0] Status.
         * @param {Object} [style=undefined] Style object describing the styling of the system window.
         * @returns {Boolean} True, if the window was opened.
         * @memberof Filemanager
         */
        _showPrompt(message = '', title = '', promptValue = '', status = 0, style = undefined) {
            this.systemWindowOpened = true;
            return this.wmApi.systemWindow_prompt(message, title, promptValue, status, style);
        }

        /**
         * Applies the font object to the passed property.
         * @param {String} propName Property name, or selector, to which the font object is to be applied.
         * @param {Object} fontObj The font object that is to be applied
         * @returns {Undefined} Undefined
         * @memberof Filemanager
         */
        sigApplyFontObject(propName, fontObj) {
            super.sigApplyFontObject(propName, fontObj);
            // Save the fontObj
            if (propName === 'sig-control-listview thead') {
                this.fontObjHeader = fontObj;
            } else if (propName === 'sig-control-listview tbody') {
                this.fontObjBody = fontObj;
            } else if (propName === 'sig-control-titlebar') {
                this.fontObjTitle = fontObj;
            }
            this._applFontObjects();
        }

        /**
         * Applies the font objects stored in the font object properties fontObjHeader, fontObjBody and fontObjTitle.
         * @private
         * @returns {Undefined} Undefined
         * @memberof Filemanager
         */
        _applFontObjects() {
            let _listView1 = null;
            let _listView2 = null;
            let _titleBar = null;
            if (this.$) {
                _listView1 = this.$.filesleft;
                _listView2 = this.$.filesright;
                _titleBar = this.$.titlebar;
            }
            if (!(_listView1 instanceof HTMLElement) && !(_listView2 instanceof HTMLElement) && !(_titleBar instanceof HTMLElement)) return;

            if (this.fontObjHeader) {
                _listView1.fontobjectheader = this.fontObjHeader;
                _listView2.fontobjectheader = this.fontObjHeader;
            } else {
                _listView1.fontobjectheader = '{}';
                _listView2.fontobjectheader = '{}';
            }
            if (this.fontObjBody) {
                _listView1.fontobjectbody = this.fontObjBody;
                _listView2.fontobjectbody = this.fontObjBody;
            } else {
                _listView1.fontobjectbody = '{}';
                _listView2.fontobjectbody = '{}';
            }
            if (this.fontObjTitle) _titleBar.fontobjecttitle = this.fontObjTitle;
            else _titleBar.fontobjecttitle = '{}';
        }
    };
};