var log = console; //just a shortcut, so it's similar to python code
var global = null;
function trim_all(s) {
    if (s != undefined){
        s = s.replace(/ /g, '');
        s = s.replace(/\n/g, '');
    }
    return s;
}

var is_empty = function(v){return typeof(v) == 'undefined' || undefined==v || null==v || ''==v;}

var is_function = function(f) { return typeof(f) == 'function'; }

/*
    Does simple (not complete) reverse to Mako 'h' filter.
*/
var unh = function(text){
    if (is_empty(text)) return text;
    return text.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&');
}
    

var fill_right = function(str, length, c){
    str = ""+str; //make a string of it
    if (is_empty(str)){
        str = "";
    }
    if (str.length >= length)
        return str;
    
    var prefix = "";
    for (var i=0; i<(length - str.length); i++)
        prefix += c;
    return prefix + str;
}
    
var startsWith = function(word, str){
    if (is_empty(word)) return false;
    return (word.match('^'+str)==str)
}

    
/* Enabled/Disabled btn based on input value */
var enable_button = function(input_id, btn_id, validator_fn){
    var v = $("#"+input_id).val();
    if (is_empty(v) || validator_fn && !validator_fn(v))
        $("#"+btn_id).attr('disabled', 'disabled');
    else
        $("#"+btn_id).attr('disabled', '');
}
/* Registeres btn to watch input text changes */
var watch_input_to_enable_btn = function(input_id, btn_id, validator_fn, dont_focus){
    $("#"+input_id).change(function(){
        enable_button(input_id, btn_id, validator_fn);
    });
    $("#"+input_id).keyup(function(){
        enable_button(input_id, btn_id, validator_fn);
    });
    $("#"+input_id).blur(function(){
        enable_button(input_id, btn_id, validator_fn);
    });
    $("#"+input_id).focus(function(){
        enable_button(input_id, btn_id, validator_fn);
    });
    $("#"+input_id).change();
    if (!dont_focus)
        $("#"+input_id).focus();
}
/* If field is empty, then show information about that. */
var warn_about_sending_form_with_empty_field = function(input_id, input_name, btn_id){
    $("#"+btn_id).click(function(){
        var v = $("#"+input_id).val();
        if (is_empty(v)){
            //TODO: i18n..
            alert("Before accepting this form, please fill up " + input_name + "!");
            return false;
        }
        return true;
    })
}


/* Functions to manage displaying of some divs, based on result of Ajax url request
 */
var TIMEOUT = 3000;
var enable_disable_div = function(answer, on_div, off_div){
    if (answer){
        $("."+off_div).hide();
        $("."+on_div).show();
    }else{
        $("."+on_div).hide();
        $("."+off_div).show();
    }
}
var watch_url_for_changes_and_enable_disable_divs = function(initial_answer, url, on_div, off_div){
    enable_disable_div(initial_answer, on_div, off_div);
    get_url_answer(url, on_div, off_div);
    
}

var get_url_answer = function(url, on_div, off_div)
{
    $.ajax({
        'url': url,
        'type': 'POST',
        'dataType': 'json',
        'success': function(answer){
            enable_disable_div(answer.result, on_div, off_div);
            setTimeout(function(){ get_url_answer(url, on_div, off_div);}, TIMEOUT);
        },
        'error': function(answer){
           //alert("We experience technical problems.");
            ;
        }
    });
}
/* -- end of functions for managing displaying of divs*/

    
/** Finds hidden 'translations' area, and extracts each 'pre' child as separate
    variable.
    @returns dictionary of values, key=pre.id
  */
var get_texts_translations = function(div_id){
    if (is_empty(div_id)){
        div_id = 'translations'
    }
    var dict = new Object();
    var jq_div = $('#' + div_id + ' > pre');
    for (var i=0; i<jq_div.length; i++){
        dict[jq_div[i].id] = jq_div[i].innerHTML;
    }
    return dict;
};

var copy_current_lang_value = function(id){
    $("#"+id).val($("#lang_selection_current_value").val());
};

var my_ajax = function(args){
    var url = args.url || "";
    var params = args.params || "";
    var error_fn = args.error_fn || "";
    var on_error_fn = args.on_error_fn || "";
    var after_fn = args.after_fn || "";
    var before_ajax_fn = args.before_ajax_fn || "";
    var max_timeout;
    var second = 1000;
    if (args.no_timeout){
        max_timeout = 999 * second;
    } else {
        max_timeout = 50 * second;
    }
    
    if (before_ajax_fn){
        before_ajax_fn();
    }
    
    $.ajax({
        type: "POST",
        url: url,
        data: {params: params},
        'dataType': 'json',
        success: function(result) {
            if (!result || result.code != "OK") {
                if (on_error_fn)
                    on_error_fn(result);
                else {
                    alert('Logic error');
                }
            } else if (result.redirection == "INNER"){
                if (!is_empty(after_fn)) {
                    after_fn(result);
                }
                if (result.success_div){
                    $("#" + result.success_div).show();
                    $("." + result.success_div).show();
                }
                
                if (result.redirection_position){
                    if ("AFTER" == result.redirection_position){
                        $("#" + result.success_div).after(result.inner_html);
                        $("." + result.success_div).after(result.inner_html);
                    } else if ("INSIDE" == result.redirection_position){
                        $("#" + result.success_div).html(result.inner_html);
                        $("." + result.success_div).html(result.inner_html);
                    };
                } else {
                    if (result.success_div){
                        $("#" + result.success_div).html(result.inner_html);
                        $("." + result.success_div).html(result.inner_html);
                    }
                }

                if (result.succes_div_timeout){
                    log.debug(result.succes_div_timeout);
                    setTimeout(function(){
                        $("#" + result.success_div).hide('slow');
                        $("." + result.success_div).hide('slow');
                    }, result.succes_div_timeout);
                }
                    
                return false;
            }
            else if (result.redirection == "REDIRECT"){
                if (!is_empty(after_fn)){
                    after_fn();
                }

                outofpage_allow_to_exit = true;
                window.location = result.success_url;
                return false;
            }
        },
        error: function(req, message, error) {
            if (error_fn) 
                error_fn(req);
            else
                if (message == "timeout")
                    alert("timeout occurs, check your internet connection and try again later");
                else {
                    if (log){
                        log.error('http error: ' + message);
                    }
                }
        },
        timeout: max_timeout
    });
};
        
function position_element(id, x,y)
{
    var lang_box = $("#"+id);
    lang_box.css("position","absolute");
    lang_box.css("top",y);
    lang_box.css("left",x);
};


function TooltipsInitialize(){
    var jq_inputs = $('input.dev-input, textarea.dev-input, select.dev-input');
        
    jq_inputs.each(function(){
        //log.debug('initializing dev-input: ' + this);
        var jq_this = $(this);
        var tooltip_configured = jq_this.attr('dev-tooltips-configured') == 'true';
        if (tooltip_configured) 
            return;
            
        var info_tooltip = jq_this.attr('dev-tooltip-info');
        var error_tooltip = jq_this.attr('dev-tooltip-error');

        TooltipsConfigure(jq_this, info_tooltip, error_tooltip)
    });
};

/* Give 'undefined' and then tooltips are NOT redefined */
function TooltipsConfigure(jq_input, info_tooltip, error_tooltip){
    jq_input.attr('dev-tooltips-configured', 'true');
    
    if (undefined != info_tooltip){
        jq_input.attr('dev-tooltip-info', info_tooltip);
    } else {
        info_tooltip = jq_input.attr('dev-tooltip-info');
    }
    if (undefined != error_tooltip){
        jq_input.attr('dev-tooltip-error', error_tooltip);
    } else {
        error_tooltip = jq_input.attr('dev-tooltip-error');
    }
    jq_input.attr('dev-tooltip-error-slides-count', 0);
    
 
    //add div containers for tips
    var jq_info_container = $('.dev-tooltip-info-container', jq_input.parent());
    if (0 == jq_info_container.length){
        jq_input.after('<div class="dev-tooltip-info-container"></div>');
    }
    var jq_error_container = $('.dev-tooltip-error-container', jq_input.parent());
    if (0 == jq_error_container.length){
        jq_input.after('<div class="dev-tooltip-error-container"></div>');
    }
    
    
    //add actual divs containing tooltip message: info
    jq_info_container = $('.dev-tooltip-info-container', jq_input.parent());
    var jq_info_div = $('.dev-tooltip-info-div', jq_info_container);
    if (0 == jq_info_div.length){
        jq_info_container.append('<div class="tooltip dev-tooltip-info-div info">' + info_tooltip + '</div>');
    } else if (1 == jq_info_div.length){
        jq_info_div.html(info_tooltip);
    }

    //add actual divs containing tooltip message: error
    jq_error_container = $('.dev-tooltip-error-container', jq_input.parent());
    var jq_error_div = $('.dev-tooltip-error-div', jq_error_container);
    if (jq_error_div.length == 0){
        jq_error_container.append('<div class="tooltip dev-tooltip-error-div error">' + error_tooltip + '</div>');
        jq_error_div = $('.dev-tooltip-error-div', jq_error_container);
    } else if (jq_error_div.length == 1){
        jq_error_div.html(error_tooltip);
    } 
    
    if (error_tooltip && !is_empty(error_tooltip)){
        jq_error_div.show();
    }

    //bind events
    jq_input.mouseover(function(){
        TooltipsOn(jq_input);
    });
    jq_input.mouseout(function(){
        TooltipsOff(jq_input);
    });
};


function TooltipsOn(jq_input){
    var in_progress = jq_input.attr('dev-tooltip-animation-in-progress') == 'true';
    if (in_progress){
        jq_input.attr('dev-tooltip-animation-in-progress-incident', 'false');
        return false;
    }
    jq_input.attr('dev-tooltip-animation-in-progress', 'true');

    if (1 != jq_input.length) {
        log.error('size of jq_input: ' + jq_input.length);
        log.error(jq_input);
        return;
    }
    
    var info_tooltip = jq_input.attr('dev-tooltip-info');
    var error_tooltip = jq_input.attr('dev-tooltip-error');
    
    var jq_info_container = $('.dev-tooltip-info-container', jq_input.parent());
    var jq_error_container = $('.dev-tooltip-error-container', jq_input.parent());
    
    
    if (!is_empty(info_tooltip)){
        var jq_info_div = $('.dev-tooltip-info-div', jq_info_container);
        
        if (jq_info_div.length == 1){
            jq_info_div.html(info_tooltip);
        }    

        $('.dev-tooltip-error-div', jq_error_container).slideUp('fast', function(){
            if (info_tooltip && !is_empty(info_tooltip)){
                $('.dev-tooltip-info-div', jq_info_container).slideDown('fast', function(){
                    if (jq_input.attr('dev-tooltip-animation-in-progress-incident') == 'true'){
                        $('.dev-tooltip-info-div', jq_info_container).hide();
                        if (error_tooltip && !is_empty(error_tooltip)){
                            $('.dev-tooltip-error-div', jq_error_container).show();
                        }
                        jq_input.attr('dev-tooltip-animation-in-progress-incident', 'false');
                    }
                    jq_input.attr('dev-tooltip-animation-in-progress', 'false');
                });
            }
        })
    }
    
    if (!is_empty(error_tooltip)) {
        var jq_error_div = $('.dev-tooltip-error-div', jq_error_container);

        if (jq_error_div.length == 1){
            jq_error_div.html(error_tooltip);
        } 
        
    }
};

function TooltipsOff(jq_input){
    var in_progress = jq_input.attr('dev-tooltip-animation-in-progress') == 'true';
    if (in_progress){
        jq_input.attr('dev-tooltip-animation-in-progress-incident', 'true');
        return false;
    }

    var jq_info_container = $('.dev-tooltip-info-container', jq_input.parent());
    var jq_error_container = $('.dev-tooltip-error-container', jq_input.parent());
    var error_tooltip = jq_input.attr('dev-tooltip-error');

    $('.dev-tooltip-info-div', jq_info_container).hide();
    if (error_tooltip && !is_empty(error_tooltip)){
        $('.dev-tooltip-error-div', jq_error_container).slideDown('normal', function(){
            //hide error tooltip when shown once or two 
            var times_shown = jq_input.attr('dev-tooltip-error-slides-count');
            jq_input.attr('dev-tooltip-error-slides-count', times_shown+1);
            
            if (times_shown > 1){
                TooltipsConfigure(jq_input, undefined, '');
            }
        });
    }
};


function highlight(jq_div, duration, bgcolor, tocolor){
    
    if (is_empty(duration)) duration = 500;
    if (is_empty(bgcolor)) bgcolor = 'white';
    if (is_empty(tocolor)) tocolor = 'yellow';
    jq_div.animate({ 
        backgroundColor: tocolor
    },{
        duration: 1
    }).animate({ 
        backgroundColor: bgcolor 
    },{
        queue: true, 
        duration: duration
    });
};


//var emailRe = "/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*\.(\w{2}|(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum))$/"
//TODO: Warning, the expression above is VERY VERY #@$#$ PERFORMANCE WRONG. 
//Try to use it and enter around 15-20 characters in email text input area in editor.. browser hangup sure!
//var emailRe = /^(\w+\.)*(\w+)@(\w+\.)+([a-zA-Z]{2,4})$/  --wrong cause does not accept "nthx-tomasz@nthx.pl"
var emailRe = /^([\w!#$%*/?|^{}`~&\'+-=_]+)*([\w!#$%*/?|^{}`~&\'+-=_]+)@([\w-]+\.)+([a-zA-Z]{2,4})$/


/* Returns true, when text is valid email */
function validator_email(text) {
    //console.debug('validator_email');
    text = trim_all(text);
    return emailRe.test(text)
        && text != ''
        && text.length > 2
        && text.substr(0,1) != '.'
        && -1 == text.indexOf('.@');
};

/* Returns true, when text is valid international phone +44 383249 - 23423 
 * WARN: update utils/utils.py#validator_phone_format ALSO to be in sync
 * */

var phoneRe = /^(\+|00)[(). -\\\/0-9]+$/

function validator_phone(text) {
    text = trim_all(text);
    var result = phoneRe.test(text)
        && text != ''
        && text.length >= 8
        && text.indexOf('++');
    return result;
};

var myTip = function(text){
    return Tip(text, BALLOON, true, ABOVE, true, OFFSETX, -17, FADEIN, 600, FADEOUT, 600, PADDING, 8, DURATION, 5000);
};
        
    
var next_id_for_generation = 0;
var generate_next_id = function(base){
    next_id_for_generation++;
    return base + '_' + (next_id_for_generation);
};

        
function roundVal(val, dec){
    /* @in: 5.1899999, dec=2
       @out: 5.19
     */
	var result = Math.round(val*Math.pow(10,dec))/Math.pow(10,dec);
	return result;
};

/* Finds element in an array and returns index exists.
   Version with _index0, uses array of tuples [ [x, y], [a, b], ...]
   @returns index of element or -1 if not found
 */
function in_array(array, element){
    for (var i in array){
        if (!is_empty(array[i]) && element == array[i]) return i;
    }
    return -1;
}
/* 
   @returns index of element or -1 if not found
 */
function val_in_array_at_index0(array, element){
    for (var i in array){
        if (!is_empty(array[i]) && element == array[i][0]) return i;
    }
    return -1;
}

var count_words = function(words){
    var counter = 0;
    var splited = words.split(/\s+/);
    for (var i in splited){
        if (!is_empty(splited[i])) counter += 1;
    }
    return counter;
}
    
function nl2br(text){
    text = escape(text);
    var re_nlchar = '';
    if(text.indexOf('%0D%0A') > -1){
        re_nlchar = /%0D%0A/g ;
    }else if(text.indexOf('%0A') > -1){
        re_nlchar = /%0A/g ;
    }else if(text.indexOf('%0D') > -1){
        re_nlchar = /%0D/g ;
    }
    if (!re_nlchar)
        return unescape( text )
    return unescape( text.replace(re_nlchar,'<br />') );
}

