function clone(obj)
{
    var ret = {};
    for(k in obj)
    {
        s_attr(ret, k, obj[k]);
    }
    return ret;
}


var PAGER_DEFAULT = {
    pagelim:15,                      // всего пейджов у пейджера
    lim_half_left:7,                 // из них слева от текущего
    lim_half_right:7,                // справа от текущего
    img_left_arr : "/img/button-left.gif",  // url картинки левой стрелки
    img_right_arr : "/img/button-right.gif", // url картинки правой стрелки
    page_size : 10
}

function PhenoPager(args)
{
    this.tag_place_id = args.tag_id;
    this.xml_data_root = args.xml_data_root;
    this.pager_conf = args.pager_sets;
    this.totalPages = 0;
    this.currentPage = 0;
    this.owner = args.owner;
}

PhenoPager.prototype.update = function(data)
{
    //alert(jQuery(this.xml_data_root  + "/total-pages", data).text());
    this.totalPages = parseInt(jQuery(this.xml_data_root  + "/total-pages", data).text());
	this.currentPage = parseInt(jQuery(this.xml_data_root + "/current-page", data).text());
    this.update_pager();
}

PhenoPager.prototype.get_page_size = function()
{
    return this.pager_conf.page_size;
}

// currentPage - номер текущей страницы
// totalPages - всего страниц в базе
PhenoPager.prototype.update_pager = function()
{
    var page_num   = this.currentPage;
    var page_total = this.totalPages;

    var img_left_arr   = this.pager_conf.img_left_arr;
    var img_right_arr  = this.pager_conf.img_right_arr;
    var lim_half_left  = this.pager_conf.lim_half_left;
    var lim_half_right = this.pager_conf.lim_half_right;
    var pagelim        = this.pager_conf.pagelim;

    var dom = $('#' + this.tag_place_id);

    dom.empty();


    if(page_num - lim_half_left <= 0 && page_total<= pagelim)
    {
        this.draw_pager_row(1, page_total, page_num, dom);
    }

    if(page_num - lim_half_left <=0 && page_total > pagelim)
    {
        this.draw_pager_row(1, pagelim,  page_num, dom);
        this.draw_arrow(pagelim + 1, dom, img_right_arr);
    }

    if(page_num - lim_half_left > 0 && page_total <= pagelim)
    {
        this.draw_pager_row(1, page_total, page_num, dom);
    }

    if(page_num - lim_half_left > 0 && page_total > pagelim && page_num + lim_half_right >= page_total)
    {
        this.draw_arrow(page_total - pagelim, dom, img_left_arr);
        this.draw_pager_row(page_total - pagelim + 1, page_total, page_num, dom);
    }

    if(page_num - lim_half_left > 0 && page_total > pagelim && page_num + lim_half_right < page_total)
    {
        if(page_num - lim_half_left - 1 > 0)
        {
            this.draw_arrow(page_num - lim_half_left - 1, dom, img_left_arr);
        }
        this.draw_pager_row(page_num - lim_half_left, page_num + lim_half_right, page_num, dom);
        if(page_num + lim_half_right + 1 <= page_total)
        {
            this.draw_arrow(page_num + lim_half_right + 1, dom, img_right_arr);
        }
    }
}

PhenoPager.prototype.draw_pager_row = function(from, to, cur_page, dom)
{
    for(var i = from; i <= to; i++)
    {
        var str = "" + i;
        var id = this.tag_place_id + i;
        if(i == cur_page + 1)
        {
            dom.createAppend('div', {'id':id}, str);
        }
        else
        {
            dom.createAppend('a', {'href': '#', 'id':id }, str);
            var self = this;
            $('#' + id).click( function(ev)
            {
                x = this.id.match(/\w(\d+)$/)[1];
                self.owner.get(x-1);
                ignore_event(ev);
            });
        }
    }
}

PhenoPager.prototype.draw_arrow = function(index, dom, img_url)
{
    var myid = this.tag_place_id+index;
    var self = this;
    dom.createAppend('a', {'href':'#', id:myid}, ['img',{'alt':'', 'src':img_url} ]);
    $('#' + myid).click(function(ev)
    {
        x = this.id.match(/\w(\d+)$/)[1];
        self.owner.get(x-1);
        ignore_event(ev);
    });
}


PhenoGrid = newClass(null, {
    /*
        xsl_file - имя xsl который будет накладываться на поступающие данные
        tag_place_id - id html tag куда будет отрисован грид
        row_callbacks - вызывается при отрисовке строк грида. назначение - установить специфичные обработчики
            контролов внутри строк грида, например кнопки редактирования
        url - серверный адрес для полчения данных в грид
        pager - объект типа PhenoPager. не обязательный
        filters - объект типа PhenoFilter. не обязательный
        redraw_filter - флаг перерисовки фильтра при обновлении грида. (часто строка фильтра статично
            определена и не требует перерисовки при обновлении грида) не обязателен, по умолчанию False
        cbox_name - имя чекбоксов в гриде для получения выбранных строк. не обязательный параметр.
    */
    constructor : function(args)
    {
        this.xsl =  load_xml_doc(args.xsl_file);
	this.xsl_file = args.xsl_file;
        this.tag_place_id = args.tag_id;
        this.row_callbacks = args.row_callbacks;
        this.url = args.url;
        this.pager = args.pager;
        if(this.pager != undefined)
            this.pager.owner = this;
        this.filters = args.filters;
        if(this.filters != undefined)
        {
            this.filters.owner = this;
            if(args.redraw_filter != undefined)
                this.redraw_filter = args.redraw_filter;
            else
                this.redraw_filter = false;

            if(this.redraw_filter == false)
                this.filters.update();
        }

        this.cbox_name = args.cbox_name;
    },
    sleepy : function(naptime){
         naptime = naptime * 1000;
	var sleeping = true;
	var now = new Date();
	var alarm;
	var startingMSeconds = now.getTime();
	//alert("starting nap at timestamp: " + startingMSeconds + "\nWill sleep for: " + naptime + " ms");
	while(sleeping){
	    alarm = new Date();
	    alarmMSeconds = alarm.getTime();
	    if(alarmMSeconds - startingMSeconds > naptime){ sleeping = false; }
	}
	//alert("Wakeup!");
    },

    update : function(data)
    {

	//$("#" + this.tag_place_id).css('border-style', 'solid');
	//alert('remove ' + this.tag_place_id);
	//this.sleepy(Math.random()*5);
        //$("#" + this.tag_place_id).empty();
	//alert('transform xsl ' + this.xsl_file);
        pooled_xsl_transform(this.xsl, data, this.tag_place_id);
	//alert('updated ' + this.tag_place_id);
	//$("#" + this.tag_place_id).css('border-style', 'none');

        if(this.row_callbacks != undefined)
            this.row_callbacks(data);
        if(this.pager != undefined)
            this.pager.update(data);
        if(this.filters != undefined)
        {
            if(this.redraw_filter == true)
                this.filters.update(data);
            else
                this.filters.hide_progress_bar();
        }
	//COUNTER -= 1;
	//alert('dwn ' + COUNTER);
    },


    get : function(n_page)
    {
        var self = this;
        var args = {
        };

        if(self.pager != undefined)
        {
            if(typeof n_page != 'number')
                n_page = self.pager.currentPage;
            args['page'] = n_page;
            args['page_size'] = self.pager.get_page_size();
        }

        if(self.filters != undefined)
        {
            var fset = self.filters.get_params();
            for(k in fset)
                args[k] = fset[k];
        }

        var own = this;
        $.ajax({
            type     : "POST",
            url      : self.url,
            data     : args,
            dataType : "xml",
            success  : function(data, s) {
		own.update(data);
	    /*
		COUNTER -= 1;
		if(COUNTER <= 0) {
                    own.update(data);
		    var e = GRID_POOL.pop();
		    while(e) {
			e.g.update(e.d);
			e = GRID_POOL.pop();
		    }
		}
		else {
		    GRID_POOL.push({g : own, d : data});
		} */
            },
            error    : on_response_error
        });
	COUNTER += 1;
	//alert(COUNTER);
    },


    get_selected_rows : function()
    {
        var ret = [];
        if(this.cbox_name != undefined)
        {
            $('input[@name="' + this.cbox_name +'"]').each( function () {
                if(this.checked == true) {
                    var x = this.id.match(/\w(\d+)$/)[1];
                    ret.push(x);
                }
            });
        }
        return ret;
    }

});

function PhenoFilter(args)
{
    this.params = {};
    if(args.args != undefined)
    {
        for(var i = 0; i< args.args.length;i++)
        {
            var v = $('#' + args.args[i]).val();
            if(v != undefined)
                this.params[args.args[i]] = v;
            else
                this.params[args.args[i]] = '';
        }
    }
    this.action_btn_id = args.action_btn_id;
    this.progress_bar_id = args.progress_bar_id;
    this.owner = args.owner;
}

PhenoFilter.prototype.fetchVals = function() {
    for(k in this.params)
    {
        this.params[k] = $('#' + k).val();
    }

}


PhenoFilter.prototype.update = function(data)
{
    // восстанавливаем значение фильтров в соответствии с значением переменных

    // TODO Check it!
    for(k in this.params)
        $('#' + k).attr('value', this.params[k])

    this.hide_progress_bar();

    if(this.action_btn_id != undefined)
    {
        var own = this;
        $('#' + this.action_btn_id).click(function(env)
        {
            $(this).attr('disabled','disabled');
            $(this).addClass('disabled');
            if(own.progress_bar_id != undefined)
                $('#' + own.progress_bar_id).css('display','inline');
            for(k in own.params)
            {
                own.params[k] = $('#' + k).val();
            }
            own.owner.get(0);
        });
    }
}

PhenoFilter.prototype.hide_progress_bar = function()
{
    if(this.action_btn_id != undefined)
    {
        $('#' + this.action_btn_id).removeAttr('disabled');
        $('#' + this.action_btn_id).removeClass('disabled');
    }
    if(this.progress_bar_id != undefined)
    {
        $('#' + this.progress_bar_id).css('display','none');
    }
}

PhenoFilter.prototype.get_params = function()
{
    return this.params;
}


