/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * CoreEngine.js
 *
 * LICENSE: This source file is subject to version 1.0 of the OpenFlyers
 * license that is available through the world-wide-web at the following
 * URI: http://www.openflyers.com/license/semifreelicense1_0.txt. If you did not receive a
 * copy of the OpenFlyers License and are unable to obtain it through the
 * web, please send a note to contact@openflyers.com so we can mail you
 * a copy immediately.
 *
 * @category    JavaScript
 * @package     OpenFlyers
 * @author      Stéphane Goossens
 * @copyright   2008 OPENFLYERS S.A.R.L. <contact@openflyers.com>
 * @license     http://www.openflyers.com/license/semifreelicense1_0.txt  OpenFlyers License
 * @link        http://www.openflyers.com, https://work.openflyers.com/index.php?title=OF_Application_engine
 * @since       Thu Dec 13 2012
 */

/**
 * coreEngine class
 */
var CoreEngine = {
    /**
     * Init properties
     */
    initProperties: function() {
//        console.log('initProperties - CoreEngine');

        /**
         * actionList
         *
         * Contains all actions that can be used by user
         *
         * @var Object
         */
        this.actionList = null;

        this.activePlugin = [];

        /**
         * advertisement
         */
        this.advertisement = {};

        /**
         * commonJavaScriptFiles
         *
         * Common JavaScript file list
         *
         * @var Array of string
         */
        this.commonJavaScriptFiles = [
            // here starts OF javascript files
            'aerogligliQuestionnaire',
            'aerogligliStats',
            'advertisement',
            'date',
            'checkPwdComplexity',
            'encrypt',
            'webFeed',
            'classes/engine/Array',
            'classes/engine/Currency',
            'classes/engine/Date',
            'classes/engine/Formula',
            'classes/engine/Math',
            'classes/engine/Moon',
            'classes/engine/Pictogram',
            'classes/engine/SearchAutocomplete',
            'classes/engine/Sexacentimal',
            'classes/engine/TopBar',
            'classes/display/Form',
            'classes/engine/Synchronization',
            'classes/engine/GenericDBAccess',
            {'classes/display/modalWindow/ModalWindow': [
                    'classes/display/modalWindow/ModalWindowAlert',
                    'classes/display/modalWindow/ModalWindowAsk',
                    'classes/display/modalWindow/ModalWindowCombobox',
                    'classes/display/modalWindow/ModalWindowCorporate',
                    'classes/display/modalWindow/ModalWindowDDT',
                    {'classes/display/modalWindow/ModalWindowDropdown' : [
                            'classes/display/modalWindow/ModalWindowUserShortcuts'
                        ]},
                    {'classes/display/modalWindow/ModalWindowForm' : [
                            'classes/display/modalWindow/ModalWindowPlatformChoice',
                            'classes/display/modalWindow/ModalWindowBookingForm',
                        ]},
                // 'classes/display/modalWindow/ModalWindowLinks',
                    'classes/display/modalWindow/ModalWindowMultiCheckbox',
                    'classes/display/modalWindow/ModalWindowPassword',
                    'classes/display/modalWindow/ModalWindowPictograms',
                    'classes/display/modalWindow/ModalWindowTextarea',
                    'classes/display/modalWindow/jquery.modalWindow'
                ]},
            {'classes/display/field/Field': [
                    'classes/display/field/Checkbox',
                    'classes/display/field/Combobox',
                    {'classes/display/field/Input': [
                            'classes/display/field/DateTimeInput',
                            'classes/display/field/DDTField',
                            'classes/display/field/FileInput',
                            'classes/display/field/MoneyInput',
                            'classes/display/field/NumberInput',
                            'classes/display/field/PasswordInput',
                            'classes/display/field/PictogramPicker',
                            'classes/display/field/RadioButton',
//                    'classes/display/field/RangeInput',
                            'classes/display/field/SexacentimalInput',
                            'classes/display/field/SubmitInput',
                            'classes/display/field/TextareaInput',
                            'classes/display/field/TextInput'
                        ]},
                    'classes/display/field/MultiCheckbox',
                    'classes/display/field/Password',
                    'classes/display/field/PictogramsBox',
                    'classes/display/field/ProgressBar',
                    'classes/display/field/Submit',
                    'classes/display/field/Textarea'
                ]},
            {'classes/display/Onboarding': [
                'pageStructures/onboarding/planning',
            ]},
            'display/dialogBox',  // TODO : to remove (https://work.openflyers.com/index.php?title=OF_DEV_Modal_Window)
            'classes/engine/touch/Touch',
            'classes/engine/touch/jquery.touch',
            'ajax/actionOnCheckedList',
            'ajax/autoCompletion',
            'pageStructures/global',
            'pageStructures/spreadsheet',
            'pageStructures/updateSpreadsheet'
        ];

        this.commonStylesheetFiles = [
            //'jQueryForked/jQueryUI/jquery-ui', // TODO: fixed error in CSS
            'jQuery/jquery.datetimepicker', //Used in datetimepicker (from jquery.datetimepicker.js) in DateTimeInput.js
            'jQuery/jQueryUI/jquery-ui-1.10.3', // Used in datetimepicker (from jquery-ui-timepicker.js), in SexacentimalInput.js
            'normalize',
            'fonts',
            'base', // replace it by base.cordova for application
            'login',
        ];

        this.commonStylesheetFilesDesktop = [
            'dashboard',
            'form',
            'menu',
            'planning',
            'table',
            'various',
            'map',
            'modalWindow',
            'info-box',
            'responsive'
        ];

        this.stylesheetFiles4Cordova = [
            'onboarding',
            'dashboard',
            'form', // replace it by form.cordova for application
            'menu',
            'modalWindow',
            'planning',
            'save',
            'info-box',
            'table', // replace it by table.cordova for application
            'various',
            'responsive'
        ];

        /**
         * displayEngine
         *
         * Reference to instance of DisplayEngine
         *
         * @var Object
         */
        this.displayEngine = null;

        /**
         * isNewUniverse
         *
         * isNewUniverse equals true on the application launch or when user has just log or after a change of unvierse
         *
         * @var Boolean
         */
        this.isNewUniverse = true;

        /**
         * loggedUser
         *
         * Contains user informations and preferences
         *
         * @var Object
         */
        this.loggedUser = {};
        
        /**
         * Onboading's instance
         * 
         * @var Onboarding
         */
        this.onboarding = null;
        
        /**
         * page
         *
         * Structure :
         * {
         *     'current' : {
         *         'action'   : String,
         *         'parameter': String,
         *         'structure': Object
         *     },
         *     'default' : {
         *         'action'   : String,
         *         'parameter': String
         *     },
         *     'previous': {
         *         'action'   : String,
         *         'parameter': String,
         *         'structure': Object
         *     }
         * }
         *
         * @var Object
         */
        this.page = null;

        /**
         * personList
         *
         * List of all the users
         *
         * @var Array
         */
        this.personList = null;

        /**
         * Plaform state
         *
         * @link https://work.openflyers.com/OF4-Authentication#Vérification-de-l%27état-de-la-plateforme
         *
         * @var Object
         */
        this.platform = {
            messageList  : [],
            remainingDays: -1,
            state        : -1,
        };

        /**
         * platformList
         *
         * Used for Android Authentication
         *
         * @var Array
         */
        this.platformList = null;

        /**
         * The minified OF4 file is used
         *
         * @var Boolean
         */
        this.usingMinifiedJavascript = false;

        /**
         * profileList
         *
         * List of all the profiles
         *
         * @type Array
         */
        this.profileList = false;

        /**
         * secureToken
         *
         * Used for encrypt password
         *
         * @var String
         */
        this.secureToken = null;

        /**
         * software
         *
         * Software properties (name, website)
         *
         * @var Object
         */
        this.software = null;

        /**
         * storage
         *
         * Used for save user ID
         *
         * @var localStorage
         */
        this.storage = window.localStorage;

        /**
         * structure
         *
         * Contains client structure information
         */
        this.structure = {};

        /**
         * tldList
         *
         * Used for save platform's TLD
         *
         * @var Array
         */
        this.tldList = null;

        /**
         * translationTag
         *
         * Contains all translation tag
         *
         * @var Object
         */
        this.translationTag = null;

        /**
         * userPlatform
         *
         * Contains the User's Platform
         *
         * TODO: merged with this.user
         *
         * @var String
         */
        this.userPlatform = null;

        /**
         * userState
         *
         * Values : logged and unlogged
         *
         * TODO: merged with this.user
         *
         * @var String
         */
        this.userState = null;

        /**
         * warningMessageList
         *
         * @var Array
         */
        this.warningMessageList = [];
    },

    /**
     * Constructor
     */
    init: function() {
//        console.log('init - CoreEngine');
        // IE < 11 is not compatible
        if (isIE && !isIE11) {
            return;
        }

        // Edge Legacy is not compatible
        if (isEdgeLegacy) {
            return;
        }

        // Reference to this
        var self = this;

        this.initProperties();

        this.commonStylesheetFiles = this.commonStylesheetFiles.concat( smartphoneDisplay ? this.stylesheetFiles4Cordova : this.commonStylesheetFilesDesktop );

        // IE 11 is unsupported
        if (isIE11) {
            this.warningMessageList.push( { tag: 'IE11_UNSUPPORTED', warningLevel: 0 } );
        }

        // edge chromium is unsupported
        if (isEdge) {
            this.warningMessageList.push( { tag: 'EDGE_UNSUPPORTED', warningLevel: 0 } );
        }

        this.userState   = 'unlogged';

        var menuAction    = '';
        var menuParameter = '';

        if (location.search) {
            var URLParameters = getURLParameters( location.search );

            if (URLParameters[0]) {
                menuAction    = URLParameters[0][1]; // Get the value of menuAction
            }
            if (URLParameters[1]) {
                menuParameter = URLParameters[1][1]; // Get the value of menuParameter
            }
        }
        this.page = {
            current: {
                action   : menuAction,
                parameter: menuParameter
            }
        };

        var callbackOnSuccess = function(result) {
            // $('head').append('<script src="http://192.168.1.4:8080/target/target-script-min.js#anonymous"></script>');
            self.initApplicationOnSuccess.call(self, result);
        };
        var callbackOnError = function(result) {
            // $('head').append('<script src="http://192.168.1.4:8080/target/target-script-min.js#anonymous"></script>');
            self.initApplicationOnError.call(self, result);
        };
        var arguments = {
            'menuAction'   : this.page.current.action,
            'menuParameter': this.page.current.parameter,
            'login'        : this.storage.getItem('login'),
            'password'     : this.storage.getItem('password'),
            'secureToken'  : this.storage.getItem('secureToken')
        };
        ajaxAction('initApplication', callbackOnSuccess, callbackOnError, null, 'json', null, arguments);
    },

    /**
     * Adds one or more JavaScript files
     *
     * Possible values :
     * javascriptFiles = 'file';
     * javascriptFiles = [ 'file1', 'file2', 'file3' ]
     * javascriptFiles = [ 'file1', { 'file2': [ 'file2a', 'file2b' ] }, 'file3' ]
     *
     * @link https://work.openflyers.com/index.php?title=OF4_Application_engine#Ajouter_un_fichier_JavaScript
     *
     * @param Mixed javascriptFiles
     * @param Mixed callbackOnSuccess
     * @param Mixed callbackOnError
     * @return void
     */
    addJavaScriptFile: function(javascriptFiles, callbackOnSuccess, callbackOnError) {
        // Reference to this
        var self = this;

        if (this.usingMinifiedJavascript) {
            callFunction(self, callbackOnSuccess);
            return;
        }

        // Counts the number of ajax request
        var ajaxRequestInProgress = 0;

        // Executed when a javascript file is downloaded
        var getJavaScriptFileOnSuccess = function () {
            ajaxRequestInProgress--;
            if (ajaxRequestInProgress === 0) {
                callFunction(self, callbackOnSuccess);
//                if (callbackOnSuccess != undefined) {
//                    if (typeof callbackOnSuccess === 'string') {
//                        window[callbackOnSuccess].call(self);
//                    }
//                    else if (typeof callbackOnSuccess === 'function') {
//                        callbackOnSuccess.call(self);
//                    }
//                }
            }
        };

        // Downloaded a javascript file
        var getJavaScriptFile = function(javascriptFile, callback) {
            ajaxRequestInProgress++;
            var filePath = 'javascript/' + javascriptFile + '.js';
            $.getScript(filePath, callback)
                .fail(function(jqxhr, settings, exception) {
                    console.warn('Couldn\'t load ' + filePath + ' (' + exception + ')');
                    callFunction(self, callbackOnError);
//                if (callbackOnError != undefined) {
//                    if (typeof callbackOnError === 'string') {
//                        window[callbackOnError].call(self);
//                    }
//                    else if (typeof callbackOnError === 'function') {
//                        callbackOnError.call(self);
//                    }
//                }
                });
        };

        // Parse a javascript file list
        var parseJavaScriptFileList = function(javascriptFileList) {
            if ($.isArray(javascriptFileList)) {
                $.each(javascriptFileList, function(index, javascriptFile) {
                    // It's a file
                    if (typeof javascriptFile === 'string') {
                        getJavaScriptFile(javascriptFile, getJavaScriptFileOnSuccess);
                    }
                    // It's a file list
                    else {
                        parseJavaScriptFileList(this);
                    }
                });
            }
            // Object is used to create waiting list
            else if ($.isPlainObject(javascriptFileList)) {
                for ( var javascriptFile in javascriptFileList) {
                    var waitingJavascriptFileList = javascriptFileList[javascriptFile];

                    getJavaScriptFile(javascriptFile, function() {
                        ajaxRequestInProgress--;
                        parseJavaScriptFileList(waitingJavascriptFileList);
                    });
                }
            }
        };

        // It's a only file 
        if (typeof javascriptFiles === 'string') {
            getJavaScriptFile(javascriptFiles, getJavaScriptFileOnSuccess);
        }
        // It's a file list
        else if ($.isArray(javascriptFiles)){
            parseJavaScriptFileList(javascriptFiles);
        }
    },

    /**
     * Call a new page
     *
     * @return void
     */
    callPage: function(pageAction, pageParameter) {
        // Reference to this
        var self = this;
        
        /**
         * callAction
         * 
         * @return void
         */
        var callAction = function() {
            //console.log('-------------------- callAction ----------------');
            var externalDisplay = action['externalDisplay'] != undefined ? action['externalDisplay'] : false;
            var pageBuilder = 'pageBuilder_' + pageAction.replace('page_', '');
            if (window[pageBuilder] == undefined) {
//              console.log(pageBuilder);
                var filePath = self.getFileWithAction(action);
                self.addJavaScriptFile(filePath, function() {
                    callDisplayEngine(pageAction, pageParameter, pageBuilder, externalDisplay);
                });
            }
            else {
//              console.log(pageAction);
//              console.log(pageParameter);
                callDisplayEngine(pageAction, pageParameter, pageBuilder, externalDisplay);
            }
        };
        
        /**
         * callDisplayEngine
         * 
         * @return void
         */
        var callDisplayEngine = function(action, parameter, structure, externalDisplay) {
//            var buildCompletePage = false;
//            if (this.isFirstPage && this.userState === 'logged') {
//                buildCompletePage = true;
//            }
            if (self.page.current.structure != undefined) {
                self.page.previous = /*clone(*/self.page.current/*)*/;
            }
            self.page.current = null;
            self.page.current = {
                'action'   : action,
                'parameter': parameter
            };
//            console.log('callPage : ' + action + ' | parameter : ' + parameter);
            self.displayEngine = new DisplayEngine(action, parameter, structure, self.isNewUniverse, externalDisplay);
            self.isNewUniverse = false;
        };
        
        pageParameter = pageParameter || null;
//        console.info('action : ' + pageAction + ' | parameter : ' + pageParameter);
        var action = this.getActionWithName(pageAction);
        if (action['version'] === 3) {
            //console.warn(pageAction);
            window.open( 'index.php?menuAction=' + pageAction + ( pageParameter != null ? '&menuParameter='+pageParameter : '' ) + '&legacyInterface=1', '_blank' );
        }
        else {
//          console.log(this.isValidAction(action));
//          console.log(this.getFileWithAction(action));
            if (!this.isValidAction(action) || this.getFileWithAction(action) == null) {
                var calledAction = pageAction;
                pageAction       = 'page_unavailableAction';
                pageParameter    = calledAction;
                console.info(pageAction);
                console.info(this.actionList);
                action           = this.getActionWithName(pageAction);
                console.info(action);
            }
            
            var onboardingIndex = Onboarding.searchOnboardingToLaunch(pageAction);
            if ( onboardingIndex !== -1) {
                initOnboarding(onboardingIndex, callAction);
            }
            else {
                callAction();
            }
            
        }
    },

    /**
     * Call a plugin (DDT, Planning, etc.)
     *
     * @param String        action
     * @param Object        parameters
     * @param jQuery Object baseElement
     * @return void
     */
    callPlugin: function(action, parameters, baseElement) {
//        console.info('callPlugin - CoreEngine');
        // Reference to this
        var self = this;
        action = this.getActionWithName(action);

        var initPlugin = function() {
            if (window[action.functionToCalled] == undefined) {
                console.warn(action.functionToCalled + ' is undefined');
                return;
            }
            if (parameters) {
                window[action.functionToCalled].call(self, baseElement, parameters);
            }
            else {
                window[action.functionToCalled].call(self, baseElement);
            }
        };

        console.dir(action);

        if (window[action.functionToCalled] == undefined) {
            var filePath = this.getFileWithAction(action);
            console.log("filePath = " + filePath + " action = " + action);
            this.addJavaScriptFile(filePath, initPlugin);
        }
        else {
            initPlugin();
        }
    },

    /**
     * callForm
     *
     * Call a form and construct it the normal way or in a modal window depending on the user's platform
     *
     * @param parentElement
     * @param pageParameter
     */
    callForm: function(formName, parentElement, pageParameter) {
        // console.info("callForm - CoreEngine");
        var formElement = createElement('div', null, null, parentElement);
        coreEngine.callPlugin('initForm', { 'name': formName }, formElement);
    },

    /**
     * getActionWithName
     *
     * @param String actionName
     * @return Object
     */
    getActionWithName: function(actionName) {
       // console.log('getActionWithName - CoreEngine');
        // console.log(actionName);
        // console.dir(this.actionList);
        // console.trace();
        var action = null;
        for ( var category in this.actionList) {
            if (this.actionList.hasOwnProperty(category)) {
                $.each(this.actionList[category].actions, function() {
                    // console.log("compare " + this.action + " - " + actionName);
                    if (this.action == actionName) {
                        action = this;
                        return false;
                    }
                });
            }
            // Stop the loop, the action is found
            if (action) {
                break;
            }
        }
//        console.dir(action);
        return action;
    },

    /**
     * getFileWithAction
     *
     * @param Object action
     * @return String
     */
    getFileWithAction: function(action) {
        return action ? action.file : null;
    },

    /**
     * getFileWithActionName
     *
     * @param String actionName
     * @return String
     */
    getFileWithActionName: function(actionName) {
        var action = null;
        action     = this.getActionWithName(actionName);

        var filePath = null;
        if (action) {
            filePath = action.file;
        }
        return filePath;
    },

    /**
     * Get parameter value
     *
     * @param String parameter
     * @return Mixed
     */
    getParameter: function(parameter) {
        if (this.structure.parameterList != undefined && this.structure.parameterList[parameter] != undefined) {
            return this.structure.parameterList[parameter];
        }
        return null;
    },

    /**
     * getPluginInstance
     *
     * @var String name
     * @return Object
     */
    //getPluginInstance: function(name) {
    //    for (var i = 0; i < this.activePlugin.length; i++) {
    //        if (this.activePlugin[i].name === name) {
    //            return this.activePlugin[i].instance;
    //        }
    //    }
    //    return null;
    //},
    getPluginInstance: function(name, onInstanceLoaded) {
        var self = this;
        var searchInstance = function(name) {
            for (var i = 0; i < self.activePlugin.length; i++) {
                if (self.activePlugin[i].name === name) {
                    return self.activePlugin[i].instance;
                }
            }
            return null;
        };
        if (onInstanceLoaded == undefined) {
            return searchInstance(name);
        }
        else {
            $(window).on('newRegisterInstance' + name, function() {
                var result = searchInstance(name);
                onInstanceLoaded(result);
                $(window).off('newRegisterInstance' + name);
            });
        }

    },

    /**
     * getTimezone
     *
     * @var Date date
     * @return Object
     */
    getTimezone: function(date) {
        var timezone = {
            name     : this.loggedUser.timezone.name,
            offset   : this.loggedUser.timezone.offset,
            offsetISO: this.loggedUser.timezone.offsetISO,
            title    : this.loggedUser.timezone.title,
        };
        if (this.loggedUser.timezone.transitions.length > 0 && date != undefined) {
            var offset    = null,
                offsetISO = null;
            for (var i = 0; i < this.loggedUser.timezone.transitions.length; i++) {
                if (date.compare( this.loggedUser.timezone.transitions[i].begin ) === -1) {
//                    console.log(this.loggedUser.timezone.transitions[i].begin);
                    break;
                }
                offset    = this.loggedUser.timezone.transitions[i].offset;
                offsetISO = this.loggedUser.timezone.transitions[i].offsetISO;
            }
            if (offset != null && offsetISO != null) {
                timezone.offset    = offset;
                timezone.offsetISO = offsetISO;
            }
        }
//        console.dir(timezone);
        return timezone;
    },

    /**
     * getTimezoneOffset
     *
     * @var Date date
     * @return Number
     */
    getTimezoneOffset: function(date) {
        if (this.loggedUser.timezone == undefined) {
            return 0;
        }
        var timezone = this.getTimezone(date);
        return timezone.offset;
    },

    /**
     * initApplication
     *
     * @var Object result
     * @return void
     */
    initApplication: function(result){
        var self                  = this;
        var ajaxRequestInProgress = 0;
        var callPageWasLaunched   = false;
        var pageAction            = null;
        var pageParameter         = null;

        var getCommonJSFilesOnSuccess = function() {
            ajaxRequestInProgress--;
            initApplicationOnComplete.call(self);
        };
        var initApplicationOnComplete = function() {
            if (callPageWasLaunched || ajaxRequestInProgress > 0) {
//                console.log('callPage: false - ' + ajaxRequestInProgress);
                return;
            }
            $('html').removeClass('preloader-page');

            if( smartphoneDisplay ) {
                $('body').addClass('smartphone');
            }
//            console.log('callPage: true');
            // Overload resize event
            self.overloadResizeEvent();

            // Initializes Touch on document element
            // @link https://work.openflyers.com/index.php?title=OF4_DEV_Touch#L.27.C3.A9v.C3.A8nement_mouseup_ne_se_d.C3.A9clenche_pas_tout_le_temps
            $(document).touch();
            // Call first page
            callPageWasLaunched = true;
            self.callPage(pageAction, pageParameter);
        };

        // Load common stylesheets if we are in dev environment
        if ( !(result.software.inProduction === true) ) {
            addStylesheetFile(self.commonStylesheetFiles, false);
        }

        // Add common JS files
        ajaxRequestInProgress++;
        // Try to get minified OF4 file
		this.addJavaScriptFile('OF4.min', function() {
            // The minified OF4 file is used
            self.usingMinifiedJavascript = true;
            // Init application
            getCommonJSFilesOnSuccess();
        }, function() {
			// If OF4.min is not found, add common javascript files
            self.addJavaScriptFile(this.commonJavaScriptFiles, getCommonJSFilesOnSuccess);
        });

        if (smartphoneDisplay) {

            if(!result['pageAction'] || result['pageAction'] !== 'page_authentication') {
                result['pageAction'] = 'page_dashboard';
            }
        }
        if (result['userState']) {
            this.userState = result['userState'];
        }

        if (result['pageAction']) {
            // pageAction = (smartphoneDisplay && result['pageAction'] !== 'page_authentication') ? 'page_empty' : result['pageAction'];
            pageAction = result['pageAction'];
        }
        if (result['pageParameter']) {
            pageParameter = result['pageParameter'];
        }

        this.platformList = result['platforms'];
        this.updateApplication(result);
        initApplicationOnComplete();
    },

    /**
     * initApplicationOnSuccess
     *
     * @var Object result
     * @return void
     */
    initApplicationOnSuccess: function(result) {
//        console.log('initApplicationOnSuccess');
        this.initApplication(result);
    },

    /**
     * initApplicationOnError
     *
     * @var Object result
     * @return void
     */
    initApplicationOnError: function(result) {
        console.log('initApplicationOnError');
        result['translationTag'] = {
            ASK_LOGIN              : 'Identifiant',
            ASK_PWD                : 'Mot de passe',
            CONNECT                : 'Se connecter',
            ERROR_INIT_APPLICATION : 'Une erreur est survenue. Vérifier votre connexion internet. Si cette dernière est fonctionnelle veuillez contacter le support',
            ERROR : 'Erreur',
            BUTTON_OK : 'OK'
        };

        result['userState'] = 'unlogged';

        result['pageAction'] = 'page_authentication',


            result['actionList'] = {
                'default' : {
                    name    : 'default',
                    title   : '',
                    icon    : '',
                    actions : [
                        {
                            action     : 'page_authentication',
                            file       : 'pageStructures/authentication',
                            mainIcon   : '',
                            subIcon    : ''
                        }
                    ]
                }
            };
        console.log(result);
        this.initApplication(result);
        this.warningMessageList.push( ['ERROR_INIT_APPLICATION', 1] );

        console.log('initApplicationOnError');
    },

    /**
     * isValidAction
     *
     * @param Mixed action
     * @return Boolean
     */
    isValidAction: function(action) {
        // Unknown action
        if (action === null) {
            return false;
        }
        // Known action
        else if (typeof action === 'object') {
            return true;
        }
        // Search the action in actionList
        else if (typeof action === 'string') {
            action = this.getActionWithName(action);
            return this.isValidAction(action);
        }
        return false;
    },

    /**
     * Overload resize event
     *
     * @return void
     */
    overloadResizeEvent: function() {
        // Reference to this
        var self = this;

        this.resizeTimer = null;
        $(window).on('resize', function() {
            if (self.resizeTimer != null) {
                clearTimeout(self.resizeTimer);
            }
            self.resizeTimer = setTimeout(function() {
                $(window).trigger('resizeOF');
            }, 100);
        });

        this.scrollTimer = null;
        $(window).on('scroll', function() {
            if (self.scrollTimer != null) {
                clearTimeout(self.scrollTimer);
            }
            self.scrollTimer = setTimeout(function() {
                $(window).trigger('scrollOF');
            }, 100);
        });
    },

    /**
     * registerPluginInstance
     *
     * @var String name
     * @var Object instance
     * @return void
     */
    //registerPluginInstance: function(name, instance) {
    //    this.activePlugin.push({
    //        name    : name,
    //        instance: instance,
    //    });
    //},
    registerPluginInstance: function(name, instance) {
        var overrideIndex = -1;
        for (var i = 0; i < this.activePlugin.length; i++) {
            if (this.activePlugin[i].name === name) {
                overrideIndex = i;
            }
        }
        var plugin = {
            name    : name,
            instance: instance,
        };

        if (overrideIndex < 0) {
            this.activePlugin.push(plugin);
        }
        else {
            this.activePlugin[overrideIndex] = plugin;
        }
        $(window).trigger('newRegisterInstance' + name);
    },

    /**
     * updateApplication
     *
     * Update application when user state change
     *
     * @param Object data
     * @return void
     */
    updateApplication: function(data) {
        console.log("updateApplication");
        // console.trace();
//        console.dir(data);
        if (data['actionList']) {
            this.actionList = clone( data['actionList'] );
//            console.log(this.actionList);
        }
        if (data['advertisement']) {
            this.advertisement = {
                adInterval      : data['advertisement']['adInterval'],
                hasAdsOnLogin   : data['advertisement']['hasAdsOnLogin'],
                hasAdvertisement: data['advertisement']['hasAdvertisement'],
            };
        }

        if (smartphoneDisplay) {
            data['defaultAction']    = 'page_dashboard';
            data['defaultParameter'] = null;
        }

        if (data['defaultAction'] != undefined) {
            this.loggedUser.defaultAction    = data['defaultAction'];
            this.loggedUser.defaultParameter = data['defaultParameter'] != undefined ? data['defaultParameter'] : null;
        }
        if (data['loggedUser']) {
            var userData = data['loggedUser'];
            if (userData['accountList'] != undefined) {
                this.loggedUser.accountList = clone( userData['accountList'] );
            }
            if (userData['database'] != undefined) {
                this.loggedUser.database = {
                    key      : userData['database']['key'],
                    profileId: userData['database']['profileId'],
                };
            }
            if (userData['IPAddress'] != undefined) {
                this.loggedUser.IPAddress = userData['IPAddress'];
            }
            if (userData['onboarding'] != undefined) {
                this.loggedUser.onboarding = [];
                for (var i = 0; i < userData['onboarding'].length; i++) {
                    this.loggedUser.onboarding.push({
                        index  : parseInt( userData['onboarding'][i]['index'] ),
                        version: parseInt( userData['onboarding'][i]['version'] ),
                    });
                }
            }
            if (userData['rightList'] != undefined) {
                this.loggedUser.rightList = clone( userData['rightList'] );
            }
            if (userData['timezone'] != undefined) {
                this.loggedUser.timezone = {
                    name       : userData['timezone']['name'],
                    offset     : userData['timezone']['offset'],
                    offsetISO  : userData['timezone']['offsetISO'],
                    title      : userData['timezone']['title'],
                    transitions: [],
                };
                for (var i = 0; i < userData['timezone']['transitions'].length; i++) {
                    this.loggedUser.timezone.transitions.push({
                        begin    : new Date(userData['timezone']['transitions'][i]['begin']),
                        offset   : userData['timezone']['transitions'][i]['offset'],
                        offsetISO: userData['timezone']['transitions'][i]['offsetISO'],
                    });
                }
//                console.info('Timezone:')
//                console.dir(this.loggedUser.timezone);
            }
            if (userData['title'] != undefined) {
                this.loggedUser.title = {
                    main     : userData['title']['main'],
                    secondary: userData['title']['secondary'],
                    short    : userData['title']['short'],
                }
            }
//            console.dir(this.loggedUser);
        }

        // @link https://work.openflyers.com/OF4-Application-engine#personList
        if(data['personList']) {
            this.personList = {
                items: [],
                name : 'person',
                title: data['personList']['title'],
                type : data['personList']['type'],
            };

            for (var i = 0; i < data['personList']['items'].length; i++) {
                var person = {
                    index          : data['personList']['items'][i]['index'],
                    allowedLocation: clone(data['personList']['items'][i]['allowedLocation']),
                    availabilities : {
                        regular    : [],
                        exceptional: [],
                    },
                    database       : {
                        key        : data['personList']['items'][i]['database']['key'],
                        email      : data['personList']['items'][i]['database']['email'],
                    },
                    profile        : clone(data['personList']['items'][i]['profile']),
                    title          : {
                        main       : data['personList']['items'][i]['title']['main'],
                        secondary  : data['personList']['items'][i]['title']['secondary'],
                        short      : data['personList']['items'][i]['title']['short'],
                    },
                };
                for (var j = 0; j < data['personList']['items'][i]['availabilities']['regular'].length; j++) {
                    person.availabilities.regular.push({
                        start_day : data['personList']['items'][i]['availabilities']['regular'][j]['start_day'],
                        end_day   : data['personList']['items'][i]['availabilities']['regular'][j]['end_day'],
                        start_hour: data['personList']['items'][i]['availabilities']['regular'][j]['start_hour'],
                        end_hour  : data['personList']['items'][i]['availabilities']['regular'][j]['end_hour'],
                    });
                }
                for (var j = 0; j < data['personList']['items'][i]['availabilities']['exceptional'].length; j++) {
                    person.availabilities.exceptional.push({
                        start_date: data['personList']['items'][i]['availabilities']['exceptional'][j]['start_date'],
                        end_date  : data['personList']['items'][i]['availabilities']['exceptional'][j]['end_date'],
                        presence  : data['personList']['items'][i]['availabilities']['exceptional'][j]['presence'],
                    });
                }
                this.personList.items.push(person);
            }
        }
        if (data['platform']) {
            var platform = data['platform'];
            if (platform['messageList'] != undefined) {
                this.platform.messageList = [];
                for (var i = 0; i < platform['messageList'].length; i++) {
                    this.platform.messageList.push({
                        tag         : platform['messageList'][i]['tag'],
                        warningLevel: platform['messageList'][i]['warningLevel'],
                    });
                    if (platform['messageList'][i]['parameters'] != undefined) {
                        this.platform.messageList[i].parameters = clone( platform['messageList'][i]['parameters'] );
                    }
                }
            }
            this.platform.hideOFMembershipAlertYear = ( platform['hideOFMembershipAlertYear'] != undefined ? platform['hideOFMembershipAlertYear'] : false );
            this.platform.remainingDays             = ( platform['remainingDays'] != undefined ? platform['remainingDays'] : -1 );
            this.platform.state                     = ( platform['state'] != undefined ? platform['state'] : -1 );
            this.platform.url                       = ( platform['url'] != undefined ? platform['url'] : '' );
        }
        if (data['profile']) {
            this.profileList = {
                items: [],
                name : 'profile',
            };
            for (var i = 0; i < data['profile']['items'].length; i++) {
                this.profileList.items.push({
                    index        : data['profile']['items'][i]['index'],
                    database     : {
                        key      : data['profile']['items'][i]['database']['key'],
                        name      : data['profile']['items'][i]['database']['name'],
                    },
                    defaultStatus: data['profile']['items'][i]['defaultStatus'],
                    picto        : data['profile']['items'][i]['picto'],
                });
            }
            //console.dir(this.profileList);
        }
        if (data['secureToken']) {
            this.secureToken = data['secureToken'];
        }
        if (data['software'] != undefined) {
            this.software = {
                name   : data['software']['name'],
                url    : data['software']['url'],
                version: data['software']['version'],
            }
        }
        if (data['structure']) {
            this.structure = {
                activity       : {
                    CSS  : data['structure']['activity'] != null && data['structure']['activity']['CSS'] != undefined ? data['structure']['activity']['CSS'] : 'default',
                    picto: data['structure']['activity'] != null && data['structure']['activity']['picto'] != undefined ? toUnicode(data['structure']['activity']['picto']) : null,
                },
                displayedPeriod: {
                    start: {
                        hour  : data['structure']['displayedPeriod']['start']['hour'],
                        minute: data['structure']['displayedPeriod']['start']['minute'],
                    },
                    end  : {
                        hour  : data['structure']['displayedPeriod']['end']['hour'],
                        minute: data['structure']['displayedPeriod']['end']['minute'],
                    },
                },
                email          : data['structure']['email'],
                name           : data['structure']['name'],
                ofName         : data['structure']['ofName'],
                parameterList  : clone( data['structure']['parameterList'] ),
                website        : data['structure']['website'],
                welcomeCell    : data['structure']['welcomeCell'],
            };

            // this.structure.activity.CSS = data['structure']['activity']['CSS'] != undefined ? data['structure']['activity']['CSS'] : 'default';
            // if (data['structure']['activity']['picto'] != undefined) {
            //     this.structure.activity.picto = toUnicode(data['structure']['activity']['picto']);
            // }
        }
        // @link https://work.openflyers.com/OF4-Application-engine#locationList
        if (data['locationList']) {
            this.locationList = clone( data['locationList'] );
        }
        if (data['translationTag']) {
            this.translationTag = clone( data['translationTag'] );
        }
    }
};
CoreEngine = Class.extend( CoreEngine );