/**
 * @version 1
 * @file 
 * Creates the basic structure necessary to implement a custom widget used in the Mobile Access.
 */
if (typeof (window.SmaCustomWidget) === "undefined") {
    /**
    * The SmaCustomWidget is the namespace used to encapsulate all the functionalities provided and required
    * to implement custom widgets.    
    * @namespace SmaCustomWidget    
    */
    window.SmaCustomWidget = {
    };
}
/**
* @namespace SmaCustomWidget
* @property {object}  proxy                          - Serves as the proxy between both the sma's host widget and the custom widget
* @property {object}  proxy.enumStatus               - Enumarator used to set the lastStatus property
* @property {object}  proxy.statusMessages           - Messages used to set the lastStatus property
* @property {object}  proxy.lastStatus               - Represents the last status after the execution of writing in properties and/or executing commands. 
* @property {object}  proxy.host                     - Allows access to the sma host widget's interfaces (window, document, and the host widget)
* @property {boolean} proxy.ready                    - The host widget won't send updates until this property is se to true.   
* @property {boolean} proxy.autoResize               - Enable the auto resize algorithm.
* @property {map}     proxy.propetiesInfo            - Carries the metadata of all the properties that belong to the custom widget. Ex.: {"security":0}
* @property {array}   proxy.securityLevels           - Integer array with 255 positions that represents current user's rigths (0 == disabled, 1 = enabled)
* @method             proxy.set                      - Set the property value in one of the directions (host or custom widget) depending of the source param's value.
* @method             proxy.on                       - Used to attach a method that will be fired every time that a specific property changes.
* @method             proxy.addOnLoad                - Used to attach a method that will be fired when the host widget is completely prepared.
* @method             proxy.addOnSecurityChange      - Used to attach a method that will be fired every time when the security levels changes.
* @method             proxy.notifyHostIsPrepared     - Used by the host widget to notify that it is completely prepared. This method will fires all the onLoad events. 
* @method             proxy.notifySecurityHasChanged - Used by the host widget to notify that the security levels has changed. This method will fires all the onSecurityChange's events. 
* @method             proxy.executeCommand           - Used to execute commands.
* @method             proxy.getPosition              - Used to get the widget position(left/top). Ex.: {"l":0px, "t":0px}
* @method             proxy.getSize                  - Used to get the widget size(width/height). Ex.: {"w":0px, "h":0px}
* @method             proxy.applyAutoSize            - Used by auto resize algorithm to modify the widget position and size.
* @method             proxy.getParentScreenSize      - Used to get the parent screen size(width/height). Ex.: {"w":0, "h":0}
*/
window.SmaCustomWidget.proxy = {
    enumStatus: {
        SUCCESS: 0,
        SERVER_ERROR: -1,
        ACTION_DISABLED: -2,
        SECURITY_REQUIREMENT: -3,
        INVALID_COMMAND: -4,
        INVALID_PROPERTY: -5
    },
    statusMessages: {
        success: "",
        serverError: null,
        actionDisabled: "Execution not allowed.",
        securityRequirement: "Security rights not enough.",
        invalidCommand: "Invalid command name.",
        invalidProperty: "Invalid property name.",
    },
    lastStatus: {
        resultCode: 0,
        message: ""
    },
    host: {
        win: null,
        doc: null,
        widget: null,
        screenId: null
    },
    ready: false,
    autoResize: true,
    propertiesInfo: {},
    securityLevels: [],
    _eventListeners: {},
    _onLoadListeners: [],
    _onSecurityChangeListeners: [],
    /**    
    *@param {object} data   - An object that follow the format: {propName:'property name', value:'value - use the type that match the prperty type'}.
    *@param {object} source - Reserved to be used by the host widget
    */
    set: function (data, source) {
        var listenner = null;

        if (source)
            listenner = this._eventListeners[data.propName];
        else
            listenner = this._eventListeners["__" + data.propName];

        if (listenner)
            listenner(data);
        else {
            this.lastStatus.resultCode = this.enumStatus.INVALID_PROPERTY;
            this.lastStatus.message = this.statusMessages.invalidProperty;
        }


    },
    /**    
    *@param {string} eventName  - The property name expected to fire an event when it changes.
    *@param {function} callback - The method that will be called when the property changes.
    *@param {object} context    - The object that will used as the 'this' into the called method.
    */
    on: function (eventName, callback, context) {
        var prop = (context ? eventName : "__" + eventName);
        this._eventListeners[prop] = callback.bind(context || this);
    },
    /**
    *@param {function} callback - The method that will be called when the widget host is completely prepared.
    *@param {object} context    - The object that will used as the 'this' into the called method.
    */
    addOnLoad: function (callback, context) {
        this._onLoadListeners.push(callback.bind(context));
    },
    /**
    *@param {function} callback - The method that will be called when the security levels changes.
    *@param {object} context    - The object that will used as the 'this' into the called method.
    */
    addOnSecurityChange: function (callback, context) {
        this._onSecurityChangeListeners.push(callback.bind(context));
    },
    notifyHostIsPrepared: function () {
        var listener = null,
            resizeManagerScript = null;
        for (var i = 0; i < this._onLoadListeners.length; i++) {
            listener = this._onLoadListeners[i];

            if (!listener) {
                console.warn("CustomWidget: Invalid onload listener.");
                continue;
            }

            listener();
        }

        try {
            if (this.autoResize) {
                resizeManagerScript = document.createElement("script");
                resizeManagerScript.onload = function () {
                    if (window.SmaCustomWidget.resizeManager) {
                        window.SmaCustomWidget.resizeManager.activate();
                    }
                }.bind(this);
                resizeManagerScript.src = "../Resources/Apis/ResizeManager.js";
                document.head.appendChild(resizeManagerScript);
            }
        } catch (e) {
            console.warn("CustomWidget: Could not load ResizeManager.js.");
        }
    },
    /**
    *@param {array} levels - Integer array with 255 positions that represents current user's rigths (0 = disabled, 1 = enabled).
    */
    notifySecurityLevelsChanged: function (levels) {
        var listener = null;
        this.securityLevels = levels;
        for (var i = 0; i < this._onSecurityChangeListeners.length; i++) {
            listener = this._onSecurityChangeListeners[i];

            if (!listener) {
                console.warn("CustomWidget: Invalid security change listener.");
                continue;
            }

            listener(this.securityLevels);
        }
    },
    /**
    *@param {string} commandName - The command name that will be executed.
    */
    executeCommand: function (commandName) {
        this.host.widget.executeCommand(commandName);
    },
    getPosition: function () {
        return this.host.widget.getPosition();
    },
    getSize: function () {
        return this.host.widget.getSize();
    },
    /**
    *@param {int} left      - Updated left for the custom widget.
    *@param {int} top       - Updated top for the custom widget.
    *@param {int} width     - Updated width for the custom widget.
    *@param {int} height    - Updated height for the custom widget.
    */
    applyAutoSize: function (left, top, width, height) {
        return this.host.widget.applyAutoSize(left, top, width, height);
    },
    getParentScreenSize: function () {
        return this.host.widget.getParentScreenSize();
    },
};