////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IkUtil (for Prototype)

var IkUtil = Class.create();

IkUtil.getActUrl = function(controller, action, params){
    var paramsString = IkUtil.httpBuildQuery(params);
    var act = (action == undefined) ? 'index' : action;
    var url = 'index.php?cntrl=' + controller + '&act=' + act;
    if (paramsString) {
        url += '&' + paramsString;
    }
    return url;
};

IkUtil.getActQueryString = function(controller, action, params){
    var paramsString = IkUtil.httpBuildQuery(params);
    var act = (action == undefined) ? 'index' : action;
    var queryString = '?cntrl=' + controller + '&act=' + act;
    if (paramsString) {
        queryString += '&' + paramsString;
    }
    return queryString;
};

IkUtil.httpBuildQuery = function(params){
    var strParts = [];
    params = $H(params);
    if (params.size()) {
        params.each(function(pair){
            var x = strParts.length;
            if (Object.isArray(pair.value)) {
                var i = 0;
                $A(pair.value).each(function(value){
                    x = strParts.length;
                    strParts[x] = (strParts.length == 0) ? '' : '&';
                    strParts[x + 1] = encodeURIComponent(pair.key) + '[' + i + ']';
                    strParts[x + 2] = '=';
                    strParts[x + 3] = encodeURIComponent(value);
                    i = i + 1;
                });
            } else {
                strParts[x] = (strParts.length == 0) ? '' : '&';
                strParts[x + 1] = encodeURIComponent(pair.key);
                strParts[x + 2] = '=';
                strParts[x + 3] = encodeURIComponent(pair.value);
            } 
        });
    }
    var paramString = strParts.join('');
    return paramString;
};

IkUtil.consoleWrite = function(message){
    var console = window['console'];
    if (console && console.log) {
        console.log(message);
    }
};

IkUtil.popup = function(url, newWindowName, optionsObject){
    var url = (url) ? url : null;
    var newWindowName = (newWindowName) ? newWindowName : null;
    var optionStringElements = new Array();
    for (var optionKey in optionsObject) {
        optionStringElements.unshift(optionKey + '=' + optionsObject[optionKey]);
    }
    window.open(url, newWindowName, optionStringElements.join(','));
};

IkUtil.parseId = function(stringId){
    var parts = stringId.split('_');
    // Return segment of string after the last underscore
    var result = null;
    if (parts.length > 0) {
        result = parts[parts.length -1];
    }
    return result;
}

IkUtil.trim = function(stringToTrim){
    return stringToTrim.replace(/^\s+|\s+$/g, '');
}

IkUtil.ltrim = function(stringToTrim){
    return stringToTrim.replace(/^\s+/, '');
}

IkUtil.rtrim = function(stringToTrim){
    return stringToTrim.replace(/\s+$/, '');
}

IkUtil.cookieSet = function(name, value, expireDays, path){
    var expiresDate = new Date();
    expiresDate.setDate(expiresDate.getDate() + expireDays);
    
    var cookieString = name + '=' + value + '; expires=' + expiresDate.toUTCString();
    
    if (path) {
        cookieString += '; path=' + path;
    }
    
    document.cookie = cookieString;
}

IkUtil.cookieGet = function(name){
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

IkUtil.cookieUnset = function(name){
    IkUtil.cookieSet(name, '', -1);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IkPreloader
var IkPreloader = Class.create({
    initialize: function(params){
        this.loadtime = null;
        this.showtime = null;
        this.showdelay = null;
        this.onPreloadCallback = (typeof params['onPreloadCallback'] == 'function') ? params['onPreloadCallback'].bind(this) : null;
        this.onShowTimeCallback = (typeof params['onShowTimeCallback'] == 'function') ? params['onShowTimeCallback'].bind(this) : null;
        
        IkUtil.consoleWrite('IkPreloader:initialize');
        var that = this;
        that.load();
    },
    getLoadTime: function() {
        return this.loadtime;
    },
    getShowTime: function() {
        return this.showtime;
    },
    getShowDelay: function() {
        return this.showdelay;
    },
    load: function() {
        IkUtil.consoleWrite('IkPreloader:load');
        var that = this;
        var d = new Date();
        that.loadtime = d.getTime();
        if (document.visibilityState && document.visibilityState !== PAGE_VISIBLE){
            IkUtil.consoleWrite('IkPreloader:load - was in preload');
            document.observe('visibilitychange', that.visibilitychange.bind(that));
            this.preload();
        } else if (document.webkitVisibilityState && document.webkitVisibilityState !== 'visible') {
            IkUtil.consoleWrite('IkPreloader:load - was in preload');
            document.observe('webkitvisibilitychange', that.webkitvisibilitychange.bind(that));
            this.preload();
        }
        else {
            IkUtil.consoleWrite('IkPreloader:load - was visible at load');
            that.show();
        }
    },
    visibilitychange: function() {
        var that = this;
        if (document.visibilityState === PAGE_VISIBLE) {
            document.stopObserving('visibilitychange', that.visibilitychange.bind(that));
            that.show();
        }
    },
    webkitvisibilitychange: function() {
        var that = this;
        if (document.webkitVisibilityState === 'visible') {
            document.stopObserving('webkitvisibilitychange', that.webkitvisibilitychange.bind(that));
            that.show();
        }
    },
    preload: function() {
        if (this.onPreloadCallback) {
            this.onPreloadCallback();
        }
    },
    show: function() {
        IkUtil.consoleWrite('IkPreloader:show');
        var that = this;
        var d = new Date();
        that.showtime = d.getTime();
        that.showdelay = (that.showtime - that.loadtime) / 1000;
        if (that.onShowTimeCallback) {
            that.onShowTimeCallback();
        }
    }
});


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IkUtilForm (for Prototype)

var IkUtilForm = Class.create();

/**
 * @param radio element or id
 * OR
 * @param form element or id
 * @param radio group name
 */
IkUtilForm.getCheckedRadiobox = function(element, radioName) {
    var result = null;
    
    if($(element).type && $(element).type.toLowerCase() == 'radio') {
        var radioGroup = $(element).name;
        var element = $(element).form;
    } else if ($(element).tagName.toLowerCase() != 'form') {
        return false;
    }
    
    var radioboxes = $(element).getInputs('radio', radioName);
    radioboxes.each(function(input){
        if (input.checked) {
            result = input;
        }
    });
    return result;
};

/**
 * @param select element or id
 * OR
 * @param form element or id
 * @param select name
 */
IkUtilForm.getSelectedOption = function(element, name) {
    var result = null;
    
    if($(element).type && $(element).type.toLowerCase() == 'select') {
        var name = $(element).name;
        var element = $(element).form;
    } else if ($(element).tagName.toLowerCase() != 'form') {
        return false;
    }
    
    var selectBox = $(element).down('select[name="' + name + '"]');
    var options = $A(selectBox.options);
    options.each(function(option){
        if (option.selected) {
            result = option;
        }
    });
    return result;
};

IkUtilForm.inputValueDefaulter = function(inputElement, defaultValue, submitElement) {
    var input = $(inputElement);
    if (input.getValue() == '') {
        input.setValue(defaultValue);
    }
    input.observe('focus', function(event){
        if (this.getValue() == defaultValue) {
            this.setValue('');
        }
    });
    input.observe('blur', function(event){
        if (this.getValue() == '') {
            this.setValue(defaultValue);
        }
    });
    if (submitElement) {
        // If the value is the default value set it back to an empty string on form submit
        var submitElement = $(submitElement);
        if (submitElement != undefined) {
            var submitEventName = (submitElement.tagName == 'FORM') ? 'submit' : 'click';
            submitElement.observe(submitEventName, function(event){
                if (input.getValue() == defaultValue) {
                    input.setValue('');
                }
            });
        }
    }
}

// In order for this function to work correctly you should set the following attributes on the input HTML
// onselect="return false" onmousedown="return false"
IkUtilForm.inputTextEditDisable = function(inputElement) {
    var input = $(inputElement);
    var origValue = '';
    input.observe('focus', function(event){
        origValue = this.getValue();
        return false;
    });
    input.observe('keydown', function(event){
        this.setValue(origValue);
    });
    input.observe('keyup', function(event){
        this.setValue(origValue);
    });
    input.observe('blur', function(event){
        this.setValue(origValue);
    }); 
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IkUtilDate (for Prototype)
//
// Functionality based on CalenderView by Justin Mecham <justin@aspect.net>

var IkUtilDate = Class.create();

IkUtilDate.MONTH_NAMES = new Array(
    'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
    'September', 'October', 'November', 'December'
);

IkUtilDate.DAY_NAMES = new Array(
    'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
    'Sunday'
);

IkUtilDate.SHORT_DAY_NAMES = new Array(
    'S', 'M', 'T', 'W', 'T', 'F', 'S', 'S'
);

IkUtilDate.MONTH_NAMES = new Array(
    'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 
    'October', 'November', 'December'
);

IkUtilDate.SHORT_MONTH_NAMES = new Array(
    'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' 
);

IkUtilDate.parse = function(str, fmt) {
    var today = new Date();
    var y     = 0;
    var m     = -1;
    var d     = 0;
    var a     = str.split(/\W+/);
    var b     = fmt.match(/%./g);
    var i     = 0, j = 0;
    var hr    = 0;
    var min   = 0;

    for (i = 0; i < a.length; ++i) {
        if (!a[i]) continue;
        switch (b[i]) {
            case "%d":
            case "%e":
                d = parseInt(a[i], 10);
            break;
            case "%m":
                m = parseInt(a[i], 10) - 1;
            break;
            case "%Y":
            case "%y":
                y = parseInt(a[i], 10);
                (y < 100) && (y += (y > 29) ? 1900 : 2000);
            break;
            case "%b":
            case "%B":
                for (j = 0; j < 12; ++j) {
                    if (IkUtilDate.MONTH_NAMES[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
                        m = j;
                        break;
                    }
                }
            break;
            case "%H":
            case "%I":
            case "%k":
            case "%l":
                hr = parseInt(a[i], 10);
            break;
            case "%P":
            case "%p":
                if (/pm/i.test(a[i]) && hr < 12)
                  hr += 12;
                else if (/am/i.test(a[i]) && hr >= 12)
                  hr -= 12;
                break;
            case "%M":
                min = parseInt(a[i], 10);
            break;
        }
    }
    if (isNaN(y)) y = today.getFullYear();
    if (isNaN(m)) m = today.getMonth();
    if (isNaN(d)) d = today.getDate();
    if (isNaN(hr)) hr = today.getHours();
    if (isNaN(min)) min = today.getMinutes();
    if (y != 0 && m != -1 && d != 0)
        return new Date(y, m, d, hr, min, 0);
    y = 0; m = -1; d = 0;
    for (i = 0; i < a.length; ++i) {
        if (a[i].search(/[a-zA-Z]+/) != -1) {
            var t = -1;
            for (j = 0; j < 12; ++j) {
                if (IkUtilDate.MONTH_NAMES[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
            }
            if (t != -1) {
                if (m != -1) {
                    d = m + 1;
                }
                m = t;
            }
        } else if (parseInt(a[i], 10) <= 12 && m == -1) {
            m = a[i] - 1;
        } else if (parseInt(a[i], 10) > 31 && y == 0) {
            y = parseInt(a[i], 10);
            (y < 100) && (y += (y > 29) ? 1900 : 2000);
        } else if (d == 0) {
            d = a[i];
        }
    }
    if (y == 0)
        y = today.getFullYear();
    if (m != -1 && d != 0)
        return new Date(y, m, d, hr, min, 0);
    return today;
};

IkUtilDate.getDayOfYear = function(date) {
    var now = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
    var then = new Date(date.getFullYear(), 0, 0, 0, 0, 0);
    var time = now - then;
    return Math.floor(time / Date.DAY);
};

IkUtilDate.getWeekNumber = function(date) {
    var d = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
    var DoW = d.getDay();
    d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
    var ms = d.valueOf(); // GMT
    d.setMonth(0);
    d.setDate(4); // Thu in Week 1
    return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
};

IkUtilDate.format = function (date, str) {
    var m = date.getMonth();
    var d = date.getDate();
    var y = date.getFullYear();
    var wn = IkUtilDate.getWeekNumber(date);
    var w = date.getDay();
    var s = {};
    var hr = date.getHours();
    var pm = (hr >= 12);
    var ir = (pm) ? (hr - 12) : hr;
    var dy = IkUtilDate.getDayOfYear(date);
    if (ir == 0)
    ir = 12;
    var min = date.getMinutes();
    var sec = date.getSeconds();
    s["%a"] = IkUtilDate.SHORT_DAY_NAMES[w]; // abbreviated weekday name [FIXME: I18N]
    s["%A"] = IkUtilDate.DAY_NAMES[w]; // full weekday name
    s["%b"] = IkUtilDate.SHORT_MONTH_NAMES[m]; // abbreviated month name [FIXME: I18N]
    s["%B"] = IkUtilDate.MONTH_NAMES[m]; // full month name
    // FIXME: %c : preferred date and time representation for the current locale
    s["%C"] = 1 + Math.floor(y / 100); // the century number
    s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
    s["%e"] = d; // the day of the month (range 1 to 31)
    // FIXME: %D : american date style: %m/%d/%y
    // FIXME: %E, %F, %G, %g, %h (man strftime)
    s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
    s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
    s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
    s["%k"] = hr;   // hour, range 0 to 23 (24h format)
    s["%l"] = ir;   // hour, range 1 to 12 (12h format)
    s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
    s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
    s["%n"] = "\n";   // a newline character
    s["%p"] = pm ? "PM" : "AM";
    s["%P"] = pm ? "pm" : "am";
    // FIXME: %r : the time in am/pm notation %I:%M:%S %p
    // FIXME: %R : the time in 24-hour notation %H:%M
    s["%s"] = Math.floor(date.getTime() / 1000);
    s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
    s["%t"] = "\t";   // a tab character
    // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
    s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
    s["%u"] = w + 1;  // the day of the week (range 1 to 7, 1 = MON)
    s["%w"] = w;    // the day of the week (range 0 to 6, 0 = SUN)
    // FIXME: %x : preferred date representation for the current locale without the time
    // FIXME: %X : preferred time representation for the current locale without the date
    s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
    s["%Y"] = y;    // year with the century
    s["%%"] = "%";    // a literal '%' character

    return str.gsub(/%./, function(match) { return s[match] || match });
};

