/**
 * @class
 * @classdesc Implements and exports RecipeHandling mixin.
 * @version 01.00.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 RecipeHandling = function (superClass) {
    return class extends superClass {

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

        /**
         * 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 RecipeHandling
        */
        _getTextObj(text = '', param = [], textList = this.controlTextList) {
            return {
                text: text,
                textList: textList,
                param: param
            };
        }

        /**
         * 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 RecipeHandling
         */
        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;
            }else if(propName === 'overlaycontentfont') {
                this.overlaycontentfont = fontObj;
            } else {
                this[propName] = fontObj;
            }
            
            this._applFontObjects();
        }

        /**
         * 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 RecipeHandling
         */
        _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 RecipeHandling
         */
        _showAlert(message = '', title = '', status = 0, style = undefined) {
            this.windowopened = 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 RecipeHandling
        */
        _showConfirm(message = '', title = '', status = 0, style = undefined) {
            this.windowopened = 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 RecipeHandling
         */
        _showPrompt(message = '', title = '', promptValue = '', status = 0, style = undefined) {
            this.windowopened = true;
            return this.wmApi.systemWindow_prompt(message, title, promptValue, status, style);
        }

        /**
         * Checks if a storage type is supported.
         * @private
         * @param {*} storageType
         * @returns {*}  If storage is supported, the storage reference will be returned and can be saved to a variable.
         * If the storage is not supported, undefined will be returned. 
         */
        _isStorageSupported(storageType) {
            try {
                storageType.setItem("test", "test");
                const testItem = storageType.getItem("test") == "test";
                storageType.removeItem("test");
                return testItem && storageType;
            } catch (err) {}
        }

        /**
         * Adds a given key to the storage.
         * @private
         * @param {*} storageType
         * @param {String} keyName
         * @param {*} keyValue
         * @returns {Number} Returns 0 if item was set. Check with getStorageItem() if value was set successfully. 
         * Returns -1 if setting item was not successful. Storage might be full or browser blocks action.
         */
        _setStorageItem(storageType, keyName, keyValue){
            const actKeyName = this.recipeHandlingStorage_KeyIdentifier + keyName;

            // necessary because storage can be full or  
            // using storage is not allowed (e.g. private mode in some browsers)
            try{
                storageType.setItem(actKeyName, keyValue);
            } catch(error){
                return -1;
            }

            return 0;
        }


        /**
         * Retrieves the value of a given key from the storage.
         * @private
         * @param {*} storageType
         * @param {String} keyName
         * @returns {*} If the key was found the value is returned. If not, null is returned.
         */
        _getStorageItem(storageType, keyName){
            const actKeyName = this.recipeHandlingStorage_KeyIdentifier + keyName;
            const keyValue = storageType.getItem(actKeyName);
            return keyValue;
        }


        /**
         * Removes an item from the storage.
         * @param {*} storageType
         * @param {String} keyName
         */
        _clearStorageItem(storageType, keyName){
            storageType.removeItem(keyName);
        }


        _clearStorage(storageType, keyNames){
            // for(let key of keyNames.length)
        }
    };
};