(function($) {

$.pi = $.extend($.pi, {
    attrEncode: function(html) {
        return $.pi.htmlEncode(html).replace(/"/g, '&quot;').replace(/'/g, '&apos;');
    },
    applicationPath: '/',
    defaultDecimalChar: '.',
    defaultDateSeparator: '/',
    defaultDateOrder: 'dmy',
    defaultDateFormat: 'dd/MM/yyyy',
    defaultDateTimeFormat: 'dd/MM/yyyy HH:mm:ss',
    localTexts: {
        ajaxErrorDialogTitle: 'ERROR!',
        alternativeFlashContent: 
            '<a href="http://www.adobe.com/go/getflashplayer">' + 
            '<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" ' +
            'alt="Get Adobe Flash player" /></a>'
    },
    localTextTable: {
        'pi.ajax_error_dialog_title': 'ERROR!',
        'pi.alternative_flash_content': 
            '<a href="http://www.adobe.com/go/getflashplayer">' + 
            '<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" ' +
            'alt="Get Adobe Flash player" /></a>'   
    },
    text: function(key, defaultText) {
        return $.pi.localTextTable[key] || defaultText || key || '';
    },
    addLocalText: function(obj, prefix) {
        if (!obj)
            return;
        prefix = prefix || '';
        for (var k in obj) {
            var actual = prefix + k;
            var o = obj[k];
            if (typeof o === "object")
                $.pi.addLocalText(o, actual + ".");
            else
                $.pi.localTextTable[actual] = o;
        }
    },
    notice: function(message, kind) {
        if ($.noticeAdd)
            $.noticeAdd({
                text: message,
                stay: false,
                stayTime: 3000,
                type: kind || 'notice',
                closeText: ''
            });
        else
            alert(message);
    },
    confirm: function(message, callback, options) {
        options = $.extend({
            dontEncode: false,
            hideCancel: false,
            okButton: $.pi.text('site.forms.ok_button'),
            cancelButton: $.pi.text('site.forms.cancel_button'),
            title: $.pi.text('site.forms.confirmation_title')
        }, options);
        if (!options.dontEncode)
            message = $.pi.htmlEncode(message);
        var buttons = {};
        buttons[options.okButton] = function() {
            dialog.dialog('close');
            if (callback)
                callback();
        };
        if (!options.hideCancel)
          buttons[options.cancelButton] = function() {
              dialog.dialog('close');
          };
        var dialog = $('<div><\/div>')
            .html(message)
            .dialog({
                autoOpen: false,
                modal: true,
                width: 360,
                height: 180,
                resizable: false,
                title: options.title,
                buttons: buttons,
                open: function() {
                    $.pi.setDefaultDialogButton($(this), 'button');
                    if (options.onOpen)
                        options.onOpen.call(this);
                },
                close: function() {
                    dialog.dialog('destroy');
                },
                overlay: {
                    opacity: 0.7, 
                    background: "black" 
                }
            });
            
            var d = dialog.parents('.ui-dialog');
            d.addClass('site-confirmation-dialog')
                
            var b = d.find('.ui-dialog-buttonpane button');
            $(b[0]).addClass('ok-button');
            $(b[1]).addClass('cancel-button');
                
            dialog.dialog('open');
    },
    format: function(source, params) {
        if ( arguments.length == 1 ) 
            return function() {
                var args = $.makeArray(arguments);
                args.unshift(source);
                return $.pi.format.apply( this, args );
            };
        if ( arguments.length > 2 && params.constructor != Array  ) {
            params = $.makeArray(arguments).slice(1);
        }
        if ( params.constructor != Array ) {
            params = [ params ];
        }
        $.each(params, function(i, n) {
            source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
        });
        return source;
    },
    setDefaultButton: function(container, buttonSelector) {
        container.unbind('keypress.defaultButton').bind('keypress.defaultButton', function (e) {   
            if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
                var button = $(buttonSelector, this);
                if (button.length) {
                    $(button[0]).trigger('click');
                    return false;   
                }
            }
        });
    },
    setDefaultDialogButton: function(container, buttonSelector) {
        $.pi.setDefaultButton(container.parent().parent(), '.ui-dialog-buttonpane ' + buttonSelector);
    },    
    htmlEncodeRegEx: /[<>&]/g,
    htmlEncodeRepFn: function(a) {
        switch (a) {
            case '&': return '&' + 'amp;';
            case '>': return '&' + 'gt;';
            case '<': return '&' + 'lt;';
        }
        return a;       
    },
    htmlEncode: function(h) { 
        var regex = $.pi.htmlEncodeRegEx;
        if (regex.test(h)) {
            return h.replace(regex, $.pi.htmlEncodeRepFn);
        }
        return h;
    },
    htmlDecode: function(h) {
        return h.replace(/&amp\\;/g, '&').replace(/&lt\\;/g, '<').replace(/&gt\\;/g, '>');
    },
    jsonAutoCompleteParser: function(data) {
        var parsed = [];
        if (data.length)
            for (var i = 0; i < data.length; i++) {
                var item = data[i];
                if (typeof data[i] == "string")
                    item = [item];
                for (var j = 0; j < item.length; j++)
                    item[j] = $.trim(item[j]);
                parsed[parsed.length] = {
                    data: item,
                    value: item[0],
                    result: item[0]
                };
            }
        return parsed;
    },
    ajaxOptions: function(options) {
        return $.extend({
            dataType: 'json',
            type: 'GET',
            cache: false,
            success: function(response, status){
                try {
                    if (response.success) {
                        if (options.proceed) 
                            options.proceed(response);
                    }
                    else if (options.message)
                        options.message(response);
                    else
                        $.pi.notice(response.message);
                } finally {
                    if (options.cleanup)
                        options.cleanup();
                }
            },
            error: function(xhr, status, e) {
                try {
                    if (xhr.status == 403) {
                        var l = null;
                        try { l = xhr.getResponseHeader('Location'); } catch (e) { l = null; }
                        if (l) {
                            top.location.href = l;
                            return;
                        }
                    }
                
                    if ($.fn.dialog && $.pi.iframeDialog) {
                        $.pi.iframeDialog({html: $.httpData(xhr) });
                    }
                    else
                        alert("ERROR:\n\n" + status);
                } finally {
                   if (options.cleanup)
                        options.cleanup();
                }
            }
        }, options);
    },
    blockBlack: function(options) {
        options = $.extend({ overlayCSS: { opacity: '0.6', backgroundColor: '#000' } }, options);
        if (options.useTimeout)
            setTimeout(function() { $.blockUI(options); }, 0);
       else
            $.blockUI(options);
    },
    blockTrans: function(options) {
        options = $.extend({ 
            message: '<img src="' + $.pi.resolveUrl('~/assets/loading.gif') + '"/>',
            css: {
                padding: '4px',
                margin: 0,
                border: '1px solid #cccccc',
                left: '18px',
                right: '',
                bottom: '18px',
                top: '',
                width: '32px',
                height: '32px',
                cursor: 'wait',
                backgroundColor: '#ffffff'
            },
            overlayCSS: { 
                opacity: '0.0',
                cursor: 'wait'
            },
            fadeOut: 0
        }, options);
        if (options.useTimeout)
            setTimeout(function() { $.blockUI(options); }, 0);
       else
            $.blockUI(options);
    },
    blockUndo: function() {
        $.unblockUI({fadeOut: 100});
    },
    parseInteger: function(value) {
        if (!(/^[-\+]?\d+$/.test(value)))
            return NaN;
        return parseInt(value, 10);
    },
    parseDecimal: function(value) {
        if (!(new RegExp("^\\s*([-\\+])?(\\d*)\\" + $.pi.defaultDecimalChar + "?(\\d*)\\s*$").test(value)))
            return NaN;
        return parseFloat(value.toString().replace($.pi.defaultDecimalChar, '.'));
    },
    parseDate: function(dateString, dateOrder)
    {
        var dateVal;
        var dArray;
        var d, m, y;

        dArray = $.pi.splitDateString(dateString);
        if (!dArray)
            return false;
         
        if (dArray.length == 3)
        {
            dateOrder = dateOrder || $.pi.defaultDateOrder;
            switch (dateOrder) {
                case "dmy" :
                    d = parseInt(dArray[0], 10);
                    m = parseInt(dArray[1], 10) - 1;
                    y = parseInt(dArray[2], 10);
                    break;
                case "ymd" :
                    d = parseInt(dArray[2], 10);
                    m = parseInt(dArray[1], 10) - 1;
                    y = parseInt(dArray[0], 10);
                    break;
                case "mdy" :
                default :
                    d = parseInt(dArray[1], 10);
                    m = parseInt(dArray[0], 10) - 1;
                    y = parseInt(dArray[2], 10);
                  break;
            }
              
            if (isNaN(d) || isNaN(m) || isNaN(y) || d < 1 || d > 31 || m < 0 || m > 11 || y > 9999 || y < 0)
                return false;
                
            if (y < 100) {
                var fullYear = new Date().getFullYear();
                var shortYearCutoff = (fullYear % 100) + 10;
                y += fullYear - fullYear % 100 + (y <= shortYearCutoff ? 0 : -100);
            }
               
            try {
                dateVal = new Date(y, m, d);
                if (isNaN(dateVal.getFullYear()))
                    return false;
            } catch(e) {
                return false;
            }
        }
        else if (dArray.length == 1)
        {
            try {
                dateVal = new Date(dArray[0]);
                if (isNaN(dateVal.getFullYear()))
                    return false;
            }
            catch(e) {
                return false;
            }
        }
        return dateVal;
    },
    replaceAll: function (old, find, rep) {
        var str = old; 
        var idx = 0;
        while (true) {
            var x = str.indexOf(find, idx);
            if (x == -1)
                break;
            str = str.replace(find, rep);
            idx += rep.length;
        }
        return str;
    },
    resolveUrl: function(url) {
        if (url && url.length && url.substr(0, 2) == "~/")
            return $.pi.applicationPath + url.substr(2);
        else
            return url;
    },
    splitDateString: function(dateString) {
        dateString = $.trim(dateString);
        if (!dateString.length)
            return;
            
        var dArray;
        if (dateString.indexOf("/") >= 0)
            dArray = dateString.split("/");
        else if (dateString.indexOf(".") >= 0)
            dArray = dateString.split(".");
        else if (dateString.indexOf("-") >= 0)
            dArray = dateString.split("-");
        else if (dateString.indexOf("\\") >= 0)
            dArray = dateString.split("\\");
        else
            dArray = [dateString];
            
        return dArray;
    },
    formatLogDateUser: function(date, user) {
        var text = "";
        if (date) {
            text = $.pi.formatDateTime($.pi.fromISODate(date), $.pi.defaultDateTimeFormat.replace(':ss', ''));
        }
        if (user && user.length) {
            if (text.length) 
                text += " ";
            text += '(' + user + ')'
        }
        return text;
    },
    fromISODate: function (string) {
        var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
            "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
            "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
        var d = string.match(new RegExp(regexp));

        var offset = 0;
        var date = new Date(d[1], 0, 1);
        if (d[3]) { date.setMonth(d[3] - 1); }
        if (d[5]) { date.setDate(d[5]); }
        if (d[7]) { date.setHours(d[7]); }
        if (d[8]) { date.setMinutes(d[8]); }
        if (d[10]) { date.setSeconds(d[10]); }
        if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
        if (d[14]) {
            offset = (Number(d[16]) * 60) + Number(d[17]);
            offset *= ((d[15] == '-') ? 1 : -1);
        }

        offset -= new Date().getTimezoneOffset();
        time = (Number(date) + (offset * 60 * 1000));
        date.setTime(Number(time));
        return date;
    },
    fromISODateNoUTC: function (string) {    
        return $.pi.toUTCDate($.pi.fromISODate(string));
    },
    getStagingClass: function(stagingStatusID, stagingBaseID) {
        if (stagingStatusID == 2)
            return 'delete';
        else if (stagingStatusID == 3 && stagingBaseID == null)
            return 'insert';
        else if (stagingStatusID == 3)
            return 'update';
        else if (stagingStatusID == 4)
            return 'revision';
        else if (stagingStatusID == 1)
            return 'published';
        else
            return '';
    },
    toISODate: function(date, format, offset) {
        if (!format) { var format = 6; }
        if (!offset) {
            var offset = 'Z';
        } else {
            var d = offset.match(/([-+])([0-9]{2}):([0-9]{2})/);
            var offsetnum = (Number(d[2]) * 60) + Number(d[3]);
            offsetnum *= ((d[1] == '-') ? -1 : 1);
            date = new Date(Number(Number(date) + (offsetnum * 60000)));
        }

        var zeropad = function (num) { return ((num < 10) ? '0' : '') + num; }

        var str = "";
        str += date.getUTCFullYear();
        if (format > 1) { str += "-" + zeropad(date.getUTCMonth() + 1); }
        if (format > 2) { str += "-" + zeropad(date.getUTCDate()); }
        if (format > 3) {
            str += "T" + zeropad(date.getUTCHours()) +
                   ":" + zeropad(date.getUTCMinutes());
        }
        if (format > 5) {
            var secs = Number(date.getUTCSeconds() + "." +
                       ((date.getUTCMilliseconds() < 100) ? '0' : '') +
                       zeropad(date.getUTCMilliseconds()));
            str += ":" + zeropad(secs);
        } else if (format > 4) { str += ":" + zeropad(date.getUTCSeconds()); }

        if (format > 3) 
            { str += offset; }
        return str;
    },
    toUTCDate: function(date) {
        var d = new Date();
        d.setTime(date.getTime() + new Date().getTimezoneOffset() * 60000);
        return d;
    },
    fromUTCDate: function(date) {
        var d = new Date();
        d.setTime(date.getTime() - new Date().getTimezoneOffset() * 60000);
        return d;
    },
    formatDecimal: function(number) {
        return number.toString().replace('.', $.pi.defaultDecimalChar);
    },   
    formatDateTime: function(date, format) {
        return $.pi.formatDate(date, format || $.pi.defaultDateTimeFormat);
    },
    formatDate: function(date, format) {
    
        var p = function p(s) {
            return (s.toString().length == 1) ? "0" + s : s;
        };  

        return (format || $.pi.defaultDateFormat).replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?|\//g, 
            function (format) {
                switch (format) {
                    case "/":
                        return $.pi.defaultDateSeparator;
                    case "hh":
                        return p(date.getHours() < 13 ? date.getHours() : (date.getHours() - 12));
                    case "h":
                        return date.getHours() < 13 ? date.getHours() : (date.getHours() - 12);
                    case "HH":
                        return p(date.getHours());
                    case "H":
                        return date.getHours();
                    case "mm":
                        return p(date.getMinutes());
                    case "m":
                        return date.getMinutes();
                    case "ss":
                        return p(date.getSeconds());
                    case "s":
                        return date.getSeconds();
                    case "yyyy":
                        return date.getFullYear();
                    case "yy":
                        return date.getFullYear().toString().substring(2, 4);
                    case "dddd":
                        return date.getDayName();
                    case "ddd":
                        return date.getDayName(true);
                    case "dd":
                        return p(date.getDate());
                    case "d":
                        return date.getDate().toString();
                    case "MM":
                        return p((date.getMonth() + 1));
                    case "M":
                        return date.getMonth() + 1;
                    case "t":
                        return date.getHours() < 12 ? 'A' : 'P';
                    case "tt":
                        return date.getHours() < 12 ? 'AM' : 'PM';
                    case "zzz":
                    case "zz":
                    case "z":
                        return "";
                }
            });
    },
    parseQueryString: function(queryString) {
        var qs;
        if (arguments.length == 0)
            qs = location.search.substring(1, location.search.length);
        else
            qs = queryString || '';
        var result = {};
        var parts = qs.split('&');
        for (var i = 0; i < parts.length; i++) {
            var pair = parts[i].split('=');
            var name = decodeURIComponent(pair[0]);
            result[name] = (pair.length >= 2 ? decodeURIComponent(pair[1]) : name);
        }
        return result;
    },   
    UrlBuilder: UrlBuilder
});

function UrlBuilder(url) {
    this.url = url || '';
    return this;
}

UrlBuilder.prototype = {
    query: function(key, value) {
        var idx = this.url.indexOf('?');
        if (idx < 0)
            this.url += '?';
        else if (idx < this.url.length - 1)
            this.url += '&';
        this.url += encodeURIComponent(key.toString()) + "=" + encodeURIComponent(value.toString());
        return this;
    },
    toString: function() {
        return this.url;
    }
}

})(jQuery);