'use strict';

var DomUtils = {
    createElement: function(tag, attributes, innerText) {
        var element = document.createElement(tag);
        for (var each in attributes) {
            element.setAttribute(each, attributes[each]);
        }
        if (innerText != undefined) {
            element.appendChild(document.createTextNode(innerText));
        }
        return element;
    },

    createForm: function(formAttributes, hiddenFields) {
        var form = this.createElement('form', formAttributes);
        for (var each in hiddenFields) {
            var hiddenElement = this.createElement('input', {
                type: 'hidden',
                name: each,
                value: hiddenFields[each]
            });
            form.appendChild(hiddenElement);
        }
        return form;
    }
};

var WindowUtils = {
    redirectTo: function(url) {
        window.location = url;
    },
    redirectToHomePage: function() {
        // variable contextPath must be specified in view (Velocity or JSP)
        WindowUtils.redirectTo(contextPath + '/adminapp/login/secureHome');
    }
};

var ClassUtils = {
    extend: function(ChildClass, ParentClass) {
        var F = function() {
        };
        F.prototype = ParentClass.prototype;
        ChildClass.prototype = new F();
        ChildClass.prototype.constructor = ChildClass;
        ChildClass.superClass = ParentClass.prototype;
    }
};
var extendClass = ClassUtils.extend;

var StringUtils = {
    /**
     * Usage with array: StringUtils.format("Hello {0}. I'm in {1}", ['John', 'Las-Vegas'])
     * Usage with var args: StringUtils.format("Hello {0}. I'm in {1}", 'John', 'Las-Vegas')
     *
     * @param string string to format
     * @param params positioned parameters (array or varArgs)
     */
    format: function(string, params) {
        if (!Array.isArray(params)) {
            params = Array.prototype.slice.call(arguments, 1);
        }
        for (var i = params.length - 1; i >= 0; i--) {
            var reg = new RegExp("\\{" + i + "\\}", "gm");
            string = string.replace(reg, params[i]);
        }
        return string;
    },

    notNullString: function(val) {
        return val != null ? val : "";
    }
};

var DateUtils = {
    format: function(date) {
        return date ?
            StringUtils.format("{0}/{1}/{2}", date.getMonth() + 1, date.getDate(), date.getFullYear()) :
            null;
    }
};

var i18n = {
    _messages: {},

    applyMessages: function(messages) {
        jQuery.extend(this._messages, messages);
    },

    applyMessage: function(code, value) {
        this._messages[code] = value;
    },

    value: function(code, params) {
        if (!(code in this._messages)) {
            return code;
        }
        var msg = this._messages[code];
        return arguments.length == 2 ?
            StringUtils.format(msg, params) :
            msg;
    }
};

function DWRErrorHandler() {
    this._handlers = {};
    this.bind('SessionExpiredException', DWRErrorHandler._sessionExpiredHandler);
}

DWRErrorHandler.prototype.bind = function(exceptionClassName, handler) {
    if (arguments.length == 1) {
        var handlers = exceptionClassName;
        for (var forClassName in handlers) {
            this.bind(forClassName, handlers[forClassName]);
        }
    } else if (arguments.length == 2) {
        this._handlers[exceptionClassName] = handler;
    }
};

DWRErrorHandler.prototype.handle = function(errorMessage, exception) {
    var handler = this._findHandlerFor(exception);
    if (handler) {
        handler(errorMessage, exception);
    } else if (exception.cause) {
        this.handle(exception.cause.message, exception.cause);
    } else {
        DWRErrorHandler._stopAllSpinners();
        Boxy.alert(errorMessage, undefined, { title: i18n.value('error') });
    }
};

DWRErrorHandler.prototype._findHandlerFor = function(exception) {
    for (var className in this._handlers) {
        if (exception instanceof window[className]) {
            return this._handlers[className];
        }
    }
};

DWRErrorHandler._stopAllSpinners = function() {
    $(':hasSpinner').spinner('stop');
};

DWRErrorHandler._sessionExpiredHandler = function() {
    DWRErrorHandler._stopAllSpinners();
    Boxy.alert(i18n.value("sessionHasExpired"), function() {
            window.location = $('#logout').attr('href');
        }, {
            title: i18n.value('error')
        }
    );
};

(function ECMA5Support() {
    /**
     * The function contains implementations of ECMA 5th edition features which are not supported by old browsers (for example, IE < 9, etc)
     */

    if (!Function.prototype.bind) {
        /**
         * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
         *
         * @param thisArg object to which function will be bound. Officially this param is optional, but actually it depends on browser.
         * In IE9 if you omit the arg, then the function will be bound to window object. In other browsers error will be raised.
         *
         * If you're going to modify bind() method, you must open utils/ecma5/bind.test.html in IE (in IE7 and IE8 modes)
         */
        Function.prototype.bind = function (thisArg) {
            if (typeof this !== "function") {
                // closest thing possible to the ECMAScript 5 internal IsCallable function
                throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
            }

            var fn = this,
                slice = Array.prototype.slice,
                args = slice.call(arguments, 1);
            return function() {
                return fn.apply(thisArg, args.concat(slice.call(arguments)));
            }
        };
    }

    if (!Array.isArray) {
        Array.isArray = function(obj) {
            return Object.prototype.toString.call(obj) == '[object Array]';
        }
    }
})();

(function jQuerySerializeObjectPlugin($) {
    $.fn.serializeObject = function() {
        var serialized = {};
        $(this).find('input:text, input[type=hidden], input[checked], textarea, select').each(function() {
            var properties = getSerializationNameFor(this).split('.'),
                lastPropertyName = properties.pop();

            makeObjectTree(serialized, properties)[lastPropertyName] = $.trim(this.value);
        });
        return serialized;
    };

    function makeObjectTree(inObject, fields) {
        var current = inObject;
        for (var i = 0; i < fields.length; i++) {
            var each = fields[i];
            if (typeof current[each] === 'undefined') {
                current[each] = {};
            }
            current = current[each];
        }
        return current;
    }

    function getSerializationNameFor(element) {
        var element$ = $(element);
        return typeof element$.data('serialization-name') === 'undefined' ?
            element$.attr('name') : element$.data('serialization-name');
    }
})(jQuery);

