/**
 * TRAVEL namespace and usefull functions
 */

if (typeof TRAVEL === 'undefined') {
    var TRAVEL = {};
}

/**
 * Namespace based on YAHOO
 */
TRAVEL.namespace = function () {
    var a = arguments, o = null, i, j, d;
    for (i = 0; i < a.length; i++) {
        d = a[i].split('.');
        o = TRAVEL;

        for (j = (d[0] === 'TRAVEL') ? 1 : 0; j < d.length; j++) {
            o[d[j]] = o[d[j]] || {};
            o = o[d[j]];
        }
    }
    return o;
};


TRAVEL.isArray = function (o) {
    if (o) {
       return o['splice'] && typeof o['length'] === 'number' && isFinite(o['length']);
    }
    return false;
};


(function () {
    var uidx = 1;

    var storage = {};

    /**
     * Generate an id that is unique among TRAVEL application
     * @method guid
     * @param pre {String} optional guid prefix
     * @return {String} the guid
     */
    TRAVEL.guid = function (pre) {
        var p = (pre) || 'trv';
        return p + '-' + uidx++;
    };

    /**
     * Make a save point for linking DOMNodes and Objects via IDs
     * @param obj {Object}
     * @param pre {String} optional guid prefix
     * @return {String} the guid
     */
    TRAVEL.savepoint = function (obj, pre) {
        var guid = TRAVEL.guid(pre);
        storage[guid] = obj;
        return guid;
    };

    /**
     * Recall data for save point
     * @param guid {String} id of save point
     * @return {Object} stored data
     */
    TRAVEL.recall = function (guid) {
        return (guid in storage) ? storage[guid] : null;
    };
})();


/**
 * Prototypal Inheritance pattern
 *
 * @author Douglas Crockford
 */
if (typeof Object.beget !== 'function') {
    Object.beget = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}


function getElementsByClass(searchClass, node, tag) {
    node = node || document;
    tag = tag || "*";
    var i, classElements = [];
    var els = node.getElementsByTagName(tag);
    var elsLen = els.length;
    var pattern = new RegExp("(^|\\s)" + searchClass + "(\\s|$)");
    for (i = 0; i < elsLen; i++) {
        if (pattern.test(els[i].className)) {
            classElements.push(els[i]);
        }
    }
    return classElements;
}

// confirms delete action
function confdel(obj) {
    var confdelstr='Are you realy sure in deleting ' + obj + '?';
    return confirm(confdelstr);
}

function inputTip(element, string) {
    (function(stringValue) {
        element.onfocus = function() {
            if (this.value == stringValue) {
                this.value = "";
            }
        }
        element.onblur = function() {
            if (this.value == "") {
                this.value = stringValue;
            }
        }
    })(string);
    element.value = string;
}
function ajaxLogin(errorCallback) {

    var data = "j_username="+$('#lgName').val().replace(/[&]/,'%26')+"&j_password="+$('#lgPass').val()+"&registerUrl="+window.location.href+"&ajax=true";

    $.ajax({
    	contentType : 'application/x-www-form-urlencoded',
        type : 'POST',
        url : baseUrl+'j_acegi_security_check',
        data : data,
        dataType : 'json',
        success : function(data) {
            if(data.url)
                window.location = data.url;
            else {
                if (errorCallback)
                    errorCallback(data.error);
            }

        }
    });
}
function ajaxLogout() {
    $.ajax({
        type : 'POST',
        url : baseUrl+'j_acegi_logout',
        data : {
            registerUrl : window.location.href,
            ajax : true
        },
        dataType : 'json',
        success : function(data) {
            if(data.url) {
                window.location = data.url;
            }
        }
    });
}

/**
 * Global "please wait" indicator for AJAX-actions
 */
(function () {

    function setPosition(evt) {
        var ele = document.getElementById("pleasewait");
        var x, y;

        if (ele && evt) {
            if (evt.pageX && evt.pageY) {
                x = evt.pageX;
                y = evt.pageY;
            } else {
                x = evt.clientX + (document.documentElement.scrollLeft ?
                                   document.documentElement.scrollLeft :
                                   document.body.scrollLeft);
                y = evt.clientY + (document.documentElement.scrollTop ?
                                   document.documentElement.scrollTop :
                                   document.body.scrollTop);
            }

            $(ele).css({'left': x + 20, 'top': y + 20});
        }
    }

    $(document).bind('click.pleasewait', setPosition);

    $.ajaxSetup({
        global: false,
        beforeSend: function () {
            // show "please wait" label
            var ele = document.getElementById("pleasewait");
            if (!ele) {
                ele = $('<div id="pleasewait" style="display: none;">' +
                            '<img src="' + baseUrl + 'new-i/s.gif" class="roller" alt="" />' +
                            '<span>' + TRAVEL.loading_message + '</span></p>' +
                        '</div>').prependTo("body");
            }

            $(document).bind('mousemove.pleasewait', setPosition);
            $(ele).fadeIn('fast');
        },
        complete: function (req, status) {
            // hide label
            var ele = document.getElementById("pleasewait");
            if (ele) {
                $(ele).fadeOut('slow', function () {
                    $(document).unbind('mousemove.pleasewait');
                });
            }

            if (status !== "success") {
                throw new Error("jQuery.ajax: " + status);
            }
        }
    });
})();

/**
 * Get decoded JSON via Ajax
 * GET and POST methods are supported
 */
(function () {
    var percentPattern =  /[%+#&]/g;

    function ajaxHelper(type, url, data, callback) {
        if (data instanceof Function) {
            callback = data;
            data = "";
        } else if (data instanceof Object) {
            data = 'sp=' + Object.toJSON(data);
        }
        data = data.replace(percentPattern, function (ch) {
            return "%" + ch.charCodeAt(0).toString(16);
        });
        try {
            $.ajax({
                'url': url,
                'data': data,
                'success': function(responseText) {
                    var json = eval("(" + responseText + ")");
                    if (typeof json.backendErrorMessage === 'undefined') {
//                        switch (json.status) {
//                            case 'error':
//                                console.error(Object.toJSON(json.error));
//                                break;
//                            case 'denied':
//                                console.error('Access denied');
//                                break;
//                            default:
                                if (callback instanceof Function) {
                                    callback(json);
                                }
//                        }
                    } else {
                        // server-side error (depreceted)
                        console.error(json.backendErrorMessage);
                    }
                },
                'type': type,
                'dataType': 'text'
            });
        } catch (ex) {
            throw new Error(ex.message);
        }
    }

    function ajaxCommandHelper(type, url, data, callback) {
        if (data instanceof Function) {
            callback = data;
            data = "";
        } else if (data instanceof Object) {
            data = 'model=' + Object.toJSON(data);
        }
        data = data.replace(percentPattern, function (ch) {
            return "%" + ch.charCodeAt(0).toString(16);
        });
        try {
            $.ajax({
                'url': url,
                'data': data,
                'success': function(responseText) {
                    var json = eval("(" + responseText + ")");
                    if (typeof json.backendErrorMessage === 'undefined') {
                        switch (json.status) {
                            case 'error':
                                console.error(Object.toJSON(json.error));
                                break;
                            case 'denied':
                                console.error('Access denied');
                                break;
                            default:
                                if (callback instanceof Function) {
                                    callback(json);
                                }
                        }
                    } else {
                        // server-side error
                        console.error(json.backendErrorMessage);
                    }
                },
                'type': type,
                'dataType': 'text'
            });
        } catch (ex) {
            throw new Error(ex.message);
        }
    }

    TRAVEL.getCommand = function (url, data, callback) {
        ajaxCommandHelper('get', url, data, callback);
    };
    TRAVEL.postCommand = function (url, data, callback) {
        ajaxCommandHelper('post', url, data, callback);
    };
    
    TRAVEL.getJSON = function (url, data, callback) {
        ajaxHelper('get', url, data, callback);
    };
    TRAVEL.postJSON = function (url, data, callback) {
        ajaxHelper('post', url, data, callback);
    };

})();

(function () {
    TRAVEL.testEmail = function(to) {
        var ajaxLink = baseUrl + 'ajaxCommand.service?command=travel.command.JSONTestMailCommand';
        var data = { "to" : to };
        TRAVEL.getJSON(ajaxLink, data, function() {});
    };
})();

/**
 * Popup component
 *
 * @singleton
 * @author Mista K.
 */
TRAVEL.Popup = (function () {
    // private storage
    var win = null;

    return {
        create: function (winTitle, parent, floatRight) {
            if (win) {
                TRAVEL.Popup.destroy();
            }
            win = document.createElement('div');
            win.id = 'travelpopup';

            var wHead = document.createElement('div');
            wHead.className = "popup-head";
            wHead.innerHTML = '<em></em><span>' + winTitle + '</span>';

            var wBody = document.createElement('div');
            wBody.className = "popup-body";

            win.appendChild(wHead);
            win.appendChild(wBody);
            $('body').prepend(win);

            var pos = $(parent).offset();
            pos.top += $(parent).height() + 2;
//            if (!!floatRight) {
                var deltaX = $(parent).width() - $(win).width();
                deltaX = (pos.left <= -deltaX) ? 0 : deltaX;
                pos.left += deltaX;
//            }


            $(win).css(pos).draggable({'handle': 'div.popup-head'});

            $('em', wHead)
                .mousedown(TRAVEL.Popup.destroy)
                .hover(
                    function () {
                        $(this).addClass('hover');
                    },
                    function () {
                        $(this).removeClass('hover');
                    }
                );

            return wBody;
        },
        destroy: function () {
            if (win) {
                $(win).draggable('destroy').remove();
                win = null;
            }
        }
    };
})();


/**
 * Paragraph formatter
 */
(function () {
    var ls = /^\s\s*/, ws = /\s/, cr = /\n+/g;
    var link = /((http|ftp):\/\/[^\s]*)/g

    TRAVEL.para = function (s) {
        if (s && s.length > 0) {
            // create links
            s = s.replace(link, '<a href="$1">$1</a>');

            // trim first with ultra fast trimmer
            var	str = s.replace(ls, ''), i = str.length;
            while (ws.test(str.charAt(--i)));
            str = str.slice(0, i + 1);
            // then wrap it with para tags
            return '<p>' + str.replace(cr, '</p><p>') + '</p>';
        }
        return '';
    }
})();

/**
 * JavaScript printf/sprintf functions.
 *
 * This code is unrestricted: you are free to use it however you like.
 *
 * The functions should work as expected, performing left or right alignment,
 * truncating strings, outputting numbers with a required precision etc.
 *
 * For complex cases, these functions follow the Perl implementations of
 * (s)printf, allowing arguments to be passed out-of-order, and to set the
 * precision or length of the output based on arguments instead of fixed
 * numbers.
 *
 * See http://perldoc.perl.org/functions/sprintf.html for more information.
 *
 * Implemented:
 * - zero and space-padding
 * - right and left-alignment,
 * - base X prefix (binary, octal and hex)
 * - positive number prefix
 * - (minimum) width
 * - precision / truncation / maximum width
 * - out of order arguments
 *
 * Not implemented (yet):
 * - vector flag
 * - size (bytes, words, long-words etc.)
 *
 * Will not implement:
 * - %n or %p (no pass-by-reference in JavaScript)
 *
 * @version 2007.04.27
 * @author Ash Searle
 */
(function () {
    // regexp pattern
    var sprintfPattern = /%%|%(\d+\$)?([-+#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;

    String.prototype.sprintf = function () {

        var a = arguments, i = 0, format = this;

        function pad(str, len, chr, leftJustify) {
            var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
            return leftJustify ? str + padding : padding + str;
        }

        function justify(value, prefix, leftJustify, minWidth, zeroPad) {
            var diff = minWidth - value.length;
            if (diff > 0) {
                if (leftJustify || !zeroPad) {
                    value = pad(value, minWidth, ' ', leftJustify);
                } else {
                    value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
                }
            }
            return value;
        }

        function formatBaseX(value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
            // Note: casts negative numbers to positive ones
            var number = value >>> 0;
            prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || '';
            value = prefix + pad(number.toString(base), precision || 0, '0', false);
            return justify(value, prefix, leftJustify, minWidth, zeroPad);
        }

        function formatString(value, leftJustify, minWidth, precision, zeroPad) {
            if (precision != null) {
                value = value.slice(0, precision);
            }
            return justify(value, '', leftJustify, minWidth, zeroPad);
        }

        function replaceCallback(substring, valueIndex, flags, minWidth, _, precision, type) {
            if (substring == '%%') return '%';

            // parse flags
            var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false;
            for (var j = 0; flags && j < flags.length; j++) switch (flags.charAt(j)) {
                case ' ': positivePrefix = ' '; break;
                case '+': positivePrefix = '+'; break;
                case '-': leftJustify = true; break;
                case '0': zeroPad = true; break;
                case '#': prefixBaseX = true; break;
            }

            // parameters may be null, undefined, empty-string or real valued
            // we want to ignore null, undefined and empty-string values

            if (!minWidth) {
                minWidth = 0;
            } else if (minWidth == '*') {
                minWidth = +a[i++];
            } else if (minWidth.charAt(0) == '*') {
                minWidth = +a[minWidth.slice(1, -1)];
            } else {
                minWidth = +minWidth;
            }

            // Note: undocumented perl feature:
            if (minWidth < 0) {
                minWidth = -minWidth;
                leftJustify = true;
            }

            if (!isFinite(minWidth)) {
                throw new Error('sprintf: (minimum-)width must be finite');
            }

            if (!precision) {
                precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0);
            } else if (precision == '*') {
                precision = +a[i++];
            } else if (precision.charAt(0) == '*') {
                precision = +a[precision.slice(1, -1)];
            } else {
                precision = +precision;
            }

            // grab value using valueIndex if required?
            var value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];

            switch (type) {
                case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad);
                case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
                case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
                case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
                case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
                case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
                case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
                case 'i':
                case 'd': {
                    var number = parseInt(+value);
                    var prefix = number < 0 ? '-' : positivePrefix;
                    value = prefix + pad(String(Math.abs(number)), precision, '0', false);
                    return justify(value, prefix, leftJustify, minWidth, zeroPad);
                }
                case 'e':
                case 'E':
                case 'f':
                case 'F':
                case 'g':
                case 'G':
                {
                    var number = +value;
                    var prefix = number < 0 ? '-' : positivePrefix;
                    var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
                    var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
                    value = prefix + Math.abs(number)[method](precision);
                    return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
                }
                default: return substring;
            }
        }

        return format.replace(sprintfPattern, replaceCallback);
    };
})();

/**
 * Convert money value to string
 *
 * @param value
 * @param zeroCent {Boolean} trim zero cents
 * @param groupDigits {Boolean} add space between group of digits
 */
(function () {
    var zeroCentPattern = /^\d+\.00$/;
    var groupDigitsPattern = /(\d)((\d\d\d)+\b)/g;

    TRAVEL.formatMoney = function (value, zeroCent, groupDigits) {

        value = Math.abs(value).toFixed(2);
        if (zeroCentPattern.test(value)) {
            value = value.substr(0, value.length - 3) + ':-';
        }
        if (groupDigits) {
            while (groupDigitsPattern.test(value)) {
                value = value.replace(groupDigitsPattern, '$1&nbsp;$2');
            }
        }
        return value;
    };

})();

/**
 * Format date helper
 * TODO: move it to TRAVEL.DateTime
 * @param value {Number|String|Date}
 * @return {String} textual presentation like 'YYYY/MM/DD'
 */
TRAVEL.formatDate = function (value) {
    var date = new Date(value);
    return '%4d/%02d/%02d'.sprintf(date.getFullYear(), date.getMonth() + 1, date.getDate());
};
/**
 * Format time helper
 * TODO: move it to TRAVEL.DateTime
 * @param value {Number|String|Date}
 * @return {String} textual presentation like 'HH:MM:SS'
 */
TRAVEL.formatTime = function (value) {
    var date = new Date(value);
    return '%02d:%02d:%02d'.sprintf(date.getHours(), date.getMinutes(), date.getSeconds());
};



(function () {

    /**
     * Button event helper
     *
     * @param ele     {jQuery}   DOMElement with class == ".btn" and contains button element
     * @param event   {String}   "click", "mousedown" or something
     * @param handler {Function} event handler function
     */
    TRAVEL.Button = function (ele, event, handler) {
        if (!$.isFunction(handler)) {
            handler = new Function();
        }
        if (ele && event) {
            $(ele).bind(event, function () {
                var button = this.getElementsByTagName('button').item(0);
                if (button && !button.disabled) {
                    handler.call(this);
                }
            });
        }
    };
})();

TRAVEL.filterSearchOptions = function (data) {

    var i, j, filtered = {};
    var parts, obj;

    filtered.query = data.query;

    // tobs
/*
    filtered.tobs = [];
    parts = data.tobs;
    for (i = 0; i < parts.length; i++) {
        obj = {'id': parts[i].id, 'subtobs': []};
        for (j = 0; j < parts[i].subtobs.length; j++) {
            if (parts[i].subtobs[j].selected) {
                obj.subtobs.push(parts[i].subtobs[j].id);
            }
        }
        filtered.tobs.push(obj);
    }
*/
    // subtobs
    filtered.subtobs = [];
    parts = data.tobs;
    for (i = 0; i < parts.length; i++) {
        for (j = 0; j < parts[i].subtobs.length; j++) {
            if (parts[i].subtobs[j].selected) {
                filtered.subtobs.push(parts[i].subtobs[j].id);
            }
        }
    }

    // keywords
    filtered.keywords = [];
    parts = data.categories;
    for (i = 0; i < parts.length; i++) {
        for (j = 0; j < parts[i].keywords.length; j++) {
            if (parts[i].keywords[j].selected) {
                filtered.keywords.push(parts[i].keywords[j].id);
            }
        }
    }

    // regions
    filtered.regions = [];
    parts = data.regions;
    for (i = 0; i < parts.length; i++) {
        if (parts[i].selected) {
            filtered.regions.push(parts[i].id);
        }
    }

    return filtered;
};

$(document).ready(function () {
    // remove SEO blocks
    $('div.seo').remove();
});