//http://localhost/tel-sez-csv/csv2js.php

function isExist(item) {return typeof(item)!=='undefined' && item!=null;}
function isSet(item,key) {return typeof(item[key])!='undefined' && item!=null;}
function isObject(item) {return typeof(item)=='object' && item!=null;}
function isArray(item) {return typeof(item)=='array' && item!=null;}

function escapeRegexp(str)
{
var reg, symbols;
spc = ('(['+'\\^$*+?.()|{}[]'.split('').join('\\'))+'])';
reg = new RegExp(spc,'g');
//alert(str)
return str.replace(reg,'\\$1');
}

window.performance = window.performance || {};
performance.now = (function() {
  return performance.now       ||
         performance.mozNow    ||
         performance.msNow     ||
         performance.oNow      ||
         performance.webkitNow ||
         function() { return new Date().getTime(); };
})();

function class_perf()
{
var root = this;
this.now  = function() {return performance.now()};
this.getTime = function()
	{
	var t1,t2, diff;
	t2 = root.now();
	t1 = root.time;
	root.time = t2;
	diff = t1!=null ? t2 - t1 : 0;
	diff = Math.floor(diff * 1000) / 1000;
	return diff;
	}
//alert(this.now)
this.time = this.now();
//this.time = null;
}

function cloneArray1(arr,start,end)	//substring
{
var i, out;
var start = isExist(start) ? start : 0;
var end   = isExist(end)   ? end   : arr.length;
out = [];
for (i=start; i<end; i++)
	{
	out[i] = arr[i];
	}
return out;
}

function cloneArray2(arr,start,end)
{
var i, j, out;
var start = isExist(start) ? start : 0;
var end   = isExist(end)   ? end   : arr.length;
out = [];
for (i=start; i<end; i++)
	{
//	out[i] = cloneArray1(arr[i]);
	out[i] = [];
	for (j=0; j<arr[i].length; j++)
		{
		out[i][j] = arr[i][j];
		}
	}
return out;
}

function objGet(id,win) {var win = win || window; return win.document.getElementById(id);}
function getSel(x)	{return x[x.selectedIndex].value;}

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

function render(tpl,data)	//tpl = "{telo}{radek}"; data = {telo:'body',radek:'tr'};
{
str = tpl;
if (isObject(data))
	{
	for (i in data)
		{
		reg = new RegExp(escapeRegexp('{'+i+'}'),'g');
		str = str.replace(reg,data[i]);
		}
	}
return str;
}


//var ee;
//ee = {};
//ee.obj_id = 'tbl_show';
//ee.obj = objGet(ee.obj_id);


//function show(pos,count)
//{
//ee.obj.innerHTML = rowsTable(rowsGet(db_map,pos,count),'zas');
//}


function toggle(obj,bool)
{
var bool = typeof(bool)!='undefined' ? bool : obj.style.display=='none';
obj.style.display = bool==true ? '' : 'none';
return bool;
}


/*
 --- reg exp filter ----
function tabFilter(tab,filters)
{
var i,j,x,y,out,tmp,l, row, reg, val, key;
//out[0] = [];
//out[1] = [];
out = [];
//x = 0;
//y = 1;
//out[k] = tab;
//for (i=0;i<filters.length;i++)
//	{
	for (i=0; i<tab.length; i++)
		{
		row = tab[i];
		bool = true;
		for (j=0; j<filters.length; j++)
			{
			key = filters[j][0];
			val = db_values[row[key]];
//alert(val)
			reg = filters[j][1];
			reg = new RegExp('^'+escapeRegexp(reg),'');
//alert(reg)
			bool &= val.search(reg) != -1;
//alert([i,val,reg,bool])
			}
		if (bool==true)
			{
			out[out.length] = row;
			}
		}
//	tmp = x; x = y; y = x;
//	}
//alert(out)
return out;
}
*/



/*
function xsort(pos,count)
{
tab = db_map;
//tab = tabFilter(tab,filters_reg);
//tab = tabFilter(tab,filters_words);
tab = tabFilterWord(tab,filters_words);
tab = sortTab(tab,cols_sort);
//tab = rowsGet(tab,pos,20);
tab = rowsGet(tab,pos,count);
//ee.obj.innerHTML = rowsTable(tab,'zas');
ee.obj.innerHTML = (tab.length>0 ? '' : '0 radku') + rowsTable(tab,'zas');
}
*/

//<td><input type="checkbox" name="{name}"  id="{id}" value="{value}"{check} onclick="filterCheck(this,{key1},{key2});"><\/td>\


//show(0,20);
//show(0,db_map.length);

filters_reg = [
[4,'3.'],
[5,'tp']
];
//cols_sort = 
//[
// column, type, order
//[3, 'strnum', 'desc'],
//[0, 'str',    'asc' ],
//[1, 'str',    'asc' ]
//];

//filters_words = [
//];


//xsort(0,db_map.length);

/*
reg = /^tp/;
str = 'tp-poe';
alert(str.search(reg)!=-1)
*/

//alert(db_map[0].length)
ENG = {};
ENG.obj = {}
ENG.obj.log     = objGet('mylog');
ENG.obj.table   = objGet('panel_table');
ENG.obj.navtop    = objGet('panel_navtop');
ENG.obj.navbottom = objGet('panel_navbottom');
ENG.obj.fr      = objGet('panel_fr');
ENG.obj.fw      = objGet('panel_fw');
ENG.obj.fs      = objGet('panel_fs');
ENG.obj.fs_area = objGet('fs_area');
ENG.obj.fs_select = [];
ENG.obj.fs_select[0] = objGet('tbl_fs_select0');
ENG.obj.fs_select[1] = objGet('tbl_fs_select1');
ENG.obj.fs_select[2] = objGet('tbl_fs_select2');
ENG.obj.panel_info = objGet('panel_info');
//ENG.obj.fw_counter = objGet('fw_counter');
ENG.db = {};
ENG.db.keys    = db_keys;
ENG.db.values  = db_values;
ENG.db.map     = db_map;
ENG.db.filters = db_filters;
ENG.db.structure = [
	'num',
	'str','str','str','str','str',
	'str','str','str','str','str',
	'str','str','str','str','str',
	'str','str','str','str','str'
	];
ENG.fs = {}
ENG.fs.data = [
{col:1, type:'str', order:'asc'}
//{col:2, type:'str', order:'desc'},
//{col:1, type:'str', order:'asc'}
/*
{col:2, type:'str', order:'desc'},
{col:1, type:'str', order:'asc'}
*/
//{col:3, type:'str', order:'desc'},
//{col:6, type:'str', order:'asc'}
	];
ENG.fs.data_example = [		// col_id, col_type, order
	{col:0 , type:ENG.db.structure[0] , order:'desc'},
	{col:17, type:ENG.db.structure[17], order:'asc'}
	];
//ENG. = [];
ENG.fw = {};
ENG.fw.data = [];
//ENG.filters_reg = [
//[4,'3.'],
//[5,'tp']
//];
ENG.fw.multi_cols = false;	//false or [[1],[2],[3],[4],[5],[6],[7],[8]] or [[1],[2,3,4],[5,6,7,8]]
ENG.filters_rows = {start:0, count:ENG.db.map.length};	// start, count
//ENG.filters_rows = [0, 50];	// start, count
ENG.tpl = {};
//<td><input type="checkbox" name="{name}" id="{id}" value="{value}" onclick="filterCheck(this,{key1},{key2});"><\/td>\
ENG.tpl.fw = "\n"+'\
<tr{class}>\
<td><input type="checkbox" name="{name}"  id="{id}" value="{value}"{check} onclick="ENG.func.filterCheck(this,{key1},{key2});"><\/td>\
<td><label for="{id}">{text}<\/label><\/td>\
<\/tr>\
';
ENG.tpl.fs0 = "\n"+'\
<option value="{value}"{check}>{text}<\/option>\
';
ENG.tpl.fs1 = "\n"+'\
<select name="{name}"  id="{id}">{data}<\/select>\
';
//ENG.tpl.table_th = '<th class="filter"><div onclick="ENG.func.filterOpenClick({key},this);">{key}<br>{value}<\/div><\/th>';//[+] 
ENG.tpl.table_th = '<th class="filter col{key}"><div onclick="ENG.func.filterOpenClick({key},this);">{value}<\/div><\/th>';	//no-edit
ENG.tpl.table_td = '<td>{value}<\/td>';

ENG.func = {};

ENG.func.init = function()
{
toggle(ENG.obj.fw,false);
toggle(ENG.obj.fs,false);
toggle(ENG.obj.fr,false);
ENG.func.fsCreateAll();
}

ENG.func.doFilters = function()
{
var tab, str;
str  = '';
perf.getTime();
	tab = cloneArray2(ENG.db.map);
str += ' clone=' + perf.getTime();
	tab = ENG.func.filterWords(tab,ENG.fw.data);
str += ' fw=' + perf.getTime();
	tab = ENG.func.filterSorts(tab,ENG.fs.data);
str += ' fs=' + perf.getTime();
	tab = ENG.func.filterRows(tab,ENG.filters_rows,ENG.fw.multi_cols);
str += ' fr=' + perf.getTime();
	tab = ENG.func.filterValues(tab);
str += ' val=' + perf.getTime();
ENG.obj.log.innerHTML = str;
return tab;
}


ENG.func.tableShow = function()
	{
	var tab, i, str;
str = '';
//	tab = [];
//	for (i=0;i<ENG.db.map.length;i++) {tab[i] = ENG.db.map[i];}	// clone
//	tab = ENG.db.map;
//	tab = ENG.func.filterWords(tab,ENG.fw.data);
//	tab = ENG.func.filterSorts(tab,ENG.fs.data);
//	tab = ENG.func.filterRows(tab,ENG.filters_rows);
tab = ENG.func.doFilters();
	ENG.obj.table.innerHTML = (tab.length>0 ? '' : '0 radku') + ENG.func.renderTable(tab,'tbl_tel');
str += ' render=' + perf.getTime();
ENG.obj.log.innerHTML += str;
	ENG.func.navShow(tab.length,ENG.db.map.length);
	ENG.func.ipShow();
	//tab = tabFilter(tab,filters_reg);
	//tab = tabFilter(tab,filters_words);
	//tab = rowsGet(tab,pos,20);
	//ee.obj.innerHTML = rowsTable(tab,'zas');
	}

ENG.func.navShow = function(a,b)
{
var str;
str  = '';
str += a + ' / ' + b;
ENG.obj.navtop.innerHTML = str;
ENG.obj.navbottom.innerHTML = str;
}

ENG.func.fwUpdate = function(key1, key2, value)
{
if (!isSet(ENG.fw.data,key1))
	{
	ENG.fw.data[key1] = [];
	}
ENG.fw.data[key1][key2] = value && isSet(ENG.db.filters[key1],key2) ? ENG.db.filters[key1][key2] : null;
}

ENG.func.filterCheck = function(obj, key1, key2)
{
//if (!isSet(ENG.fw.data,key1))
//	{
//	ENG.fw.data[key1] = [];
//	}
//ENG.fw.data[key1][key2] = !obj.checked ? ENG.db.filters[key1][key2] : null;
ENG.func.fwUpdate(key1,key2,!obj.checked);
ENG.func.fwCreate();
ENG.func.tableShow();
}

ENG.func.fwCreate = function(show)
{
var i, str, id, name, data1, data2, value, check, filter_data, tpl, checkedobj2, key;
show = typeof(show)!='undefined' ? show : true;
obj2 = ENG.obj.fw;
key  = ENG.fw.key;
ENG.fw.opened = key;
filter_data = ENG.db.filters[key];
tpl = ENG.tpl.fw;
//if (typeof(filters_words[key])!='undefined' && filters_words[key]!=null)
//	{
//	data1 = filters_words[key]
//	}
//else	{
//	data1 = db_filters[key];
//	}
str = '';
data2 = [];
checked = 0;
for (i=0; i<filter_data.length; i++)
	{
	check = true;
	if (isSet(ENG.fw.data,key) && isSet(ENG.fw.data[key],i) && ENG.fw.data[key][i]!=null)
		{check = false;}
	id    = "ch_"+i;
	name  = "ch[]";
	value = filter_data[i];
	data2[data2.length] = {class:'',check:check==true?' checked="checked"':'', name:name, id:id, key1:key, key2:i, value:value, text:ENG.db.values[value]};
	if (check==true) {checked++;}
	}
//data2.sort( function(a,b){return a.text>b.text;} );
data2.sort( function(a,b){return compare_func.asc[ENG.db.structure[key]](a.text,b.text);} );
for (i=0; i<data2.length; i++)
	{
	str += render(tpl,data2[i]);
	}
//alert(.)
obj2.style.marginLeft = ENG.fw.left + 'px';
obj2.style.width   = ENG.fw.width + 'px';
obj2.innerHTML = '<div class=count>' + checked + ' / ' + filter_data.length + '<\/div> ' + "\n" + '<div class="filter"><table class="filter">' + str + '<\/table><\/div>';
obj2.style.display = show ? 'block' : 'none';
// (id='+key+')
}

ENG.func.filterOpenClick = function(key, obj1)
{
var obj1,obj2, bool;
obj2 = ENG.obj.fw;
bool = !(ENG.fw.opened>=0 && ENG.fw.opened==key)
bool = toggle(obj2,bool);
//ENG.func.ipShow();
ENG.fw.opened = -1;
if (bool==false) {return;}
obj1 = obj1.parentNode;
ENG.fw.key   = key;
ENG.fw.left  = obj1.offsetLeft;
ENG.fw.width = obj1.offsetWidth + 22;	//22 checkbox, scrollbar, space
ENG.func.fwCreate();
}





ENG.func.fwCmpOr = function(row,filters,cols)
{
var bool0, bool1, col;
bool0 = false;
		//bool1 = true;
		//row   = tab[i];
		for (j=0; j<cols.length; j++)
			{
			bool1 = true;
			col = cols[j];
			if (isSet(filters,col) && filters[col]!=null)
				{
				filter = filters[col];
//alert(filter.toSource())
//				bool2 = true;
				for (k=0; k<filter.length; k++)	// filtry na slova jsou v negaci
					{
					if (isSet(filter,k) && filter[k]!==null)
						{
//						if (filter[j]===row[j]) {bool2 = false; break;}
						if (filter[k]===row[col]) {bool1 = false; break;}
						}
					}
//			bool1 &= bool2;
//				if (bool1==false) {break;}
				}
			bool0 |= bool1;
			}
return bool0;
}

ENG.func.filterWords = function(tab,filters)
{
if (filters.length===0) {return tab;}
//return tab;
var i,j,k,x,y,out,tmp,l, row, reg, val, key, bool1, bool2, multi_cols, cols;
out = [];
multi_cols = ENG.fw.multi_cols;
if (!multi_cols)
	{
	multi_cols = [];
	row   = tab[0];
	for (j=0; j<row.length; j++)
		{
		multi_cols[j] = [j];
		}	
	}
//alert(tab.length)
//alert(multi_cols[1])
	for (i=0; i<tab.length; i++)
		{
		bool1 = true;
		row   = tab[i];
//		ENG.func.fwCmpOr(row,filters,cols);
		for (ii=0; ii<multi_cols.length; ii++)
			{
			cols = multi_cols[ii];
//alert(cols)
			bool1 &= ENG.func.fwCmpOr(row,filters,cols);
/*
		for (j=0; j<row.length; j++)
			{
			if (isSet(filters,j) && filters[j]!=null)
				{
				filter = filters[j];
//alert(filter.toSource())
//				bool2 = true;
				for (k=0; k<filter.length; k++)	// filtry na slova jsou v negaci
					{
					if (isSet(filter,k) && filter[k]!==null)
						{
//						if (filter[j]===row[j]) {bool2 = false; break;}
						if (filter[k]===row[j]) {bool1 = false; break;}
						}
					}
//			bool1 &= bool2;
//				if (bool1==false) {break;}
				if (bool1==false) {break;}
				}
*/
			if (bool1==false) {break;}
			}
		if (bool1==true)
			{
			out[out.length] = row;
			}
		}
return out;
}

ENG.func.filterSorts = function(tab,cols_sort)
{
var i,c;
if (cols_sort.length<=0) {return tab;}
cols_func = [];
for (i in cols_sort)
	{
	c = cols_sort[i];
	c.func = compare_func[c.order][c.type];
	cols_func[i] = c;
	}
//alert(tab)
return tab.sort(compareRows);
}

var compare_func = {
'asc':	{
	// compare string with number
//	'str': function(a,b) {if (a.length<b.length||a<b) {return -1;} else {if (a.length>b.length||a>b) {return 1;}}; return 0;},
	'str': function(a,b) {if (a.length<b.length||a<b) {return -1;}; if (a.length>b.length||a>b) {return 1;}; return 0;},
	// compare number
	'num': function(a,b) {return a*1-b*1;},
	// compare string
	'strnum': function(a,b) {return ((a.replace(/[^-.0-9]/g,''))*1-(b.replace(/[^-.0-9]/g,''))*1);}
	},
'desc':	{
	// compare string
//	'str': function(b,a) {if (a<b) {return -1;}; if (a>b) {return 1;}; return 0;},
//	'str': function(b,a) {if (a.length<b.length||a<b) {return -1;} else {if (a.length>b.length||a>b) {return 1;}}; return 0;},
	'str': function(b,a) {if (a.length<b.length||a<b) {return -1;}; if (a.length>b.length||a>b) {return 1;}; return 0;},
	// compare number
	'num': function(b,a) {return a*1-b*1;},
	// compare string with number
	'strnum': function(b,a) {return ((a.replace(/[^-.0-9]/g,''))*1-(b.replace(/[^-.0-9]/g,''))*1);}
	},
// compare random, >0.5 for more swaping
'rnd': {'rnd': function(a,b) {return 0.66 - Math.random();}}
}
// compare date 2010-07-22 15:30
compare_func.asc.date  = compare_func.asc.strnum;
compare_func.desc.date = compare_func.desc.strnum;
/*
compare_func.asc.str  = function(a,b) {
//if (a<b) {return -1;}; if (a>b) {return 1;}; return 0;
	var c,d, x; 
//	c = a.substr(0,1); 
//	d = b.substr(0,1); 
//return compare_func.asc.strfull(a,b);
	x = compare_func.asc.strfull(a.substr(0,3),b.substr(0,3));
	if (x===0) {x = compare_func.asc.strfull(a,b);}
	return x;
	}
compare_func.desc.str  = function(a,b) {
	return compare_func.asc.str(b,a);
	}
*/

function compareRows(a,b)
{
var i,c,d, aa, bb;
for (i in cols_func)
	{
	c = cols_func[i];
	aa = a[c['col']]
	bb = b[c['col']]
	aa = ENG.db.values[aa];
	bb = ENG.db.values[bb];
	d = c['func'](aa,bb);
	if (d!=0) {return d;}
	}
return 0;
}

ENG.func.filterRows = function(tab, filter)
{
var start, end;
out   = [];
start = filter.start;
end   = filter.count;
end   = end>tab.length ? tab.length : end;
if (end == tab.length) {return tab;}
return cloneArray2(ENG.db.map,start,end);
}

ENG.tpl.fr = {};
ENG.tpl.fr.all    = '<form name="form_fr">{filter_rows}</form>';
ENG.tpl.fr.input  = '<label>{label} <input type="text" name="{name}" value="{value}"></label>';
ENG.tpl.fr.button = '<input type="button" value="Pouzit" onclick="ENG.func.frCloseClick();">';

ENG.func.frOpenClick = function()
{
var bool, str, tpl;
bool = toggle(ENG.obj.fr);
if (bool)
	{
	tpl = ENG.tpl.fr;
	str  = '';
	str += render(tpl.input,{label:'start',name:'fr_start',value:ENG.filters_rows.start});
	str += render(tpl.input,{label:'count',name:'fr_count',value:ENG.filters_rows.count});
	str += render(tpl.button);
	ENG.obj.fr.innerHTML = render(tpl.all,{filter_rows:str});
	}
else	{
	ENG.func.frCloseClick();
	}
}

ENG.func.frCloseClick = function()
{
var form;
form = document.forms['form_fr'];
//alert (form['fr_count'].value);
if (form)
	{
//alert([
//isSet(form,'fr_start'),
//isSet(form,'fr_count')
//])

	ENG.filters_rows.start = isSet(form,'fr_start') ? form['fr_start'].value * 1 : ENG.filters_rows.start;
	ENG.filters_rows.count = isSet(form,'fr_count') ? form['fr_count'].value * 1 : ENG.filters_rows.count;
	}
//alert(ENG.filters_rows.toSource())
toggle(ENG.obj.fr, false);
ENG.func.tableShow();
}

/*
k = 0;
for (i=start; i<count; ++i)
	{
//	row = tab[i];
//	out[k] = [];
//	for (j=0; j<row.length; j++)
//		{
//		out[k][j] = ENG.db.values[row[j]] ? ENG.db.values[row[j]] : '';
//		}
//	out[k] = row;
	out[k] = tab[i];
	++k;
	}
return out;
}
*/

ENG.func.filterValues = function(tab)
{
//return tab;
var i,j;
for (i=0; i<tab.length; ++i)
	{
	row = tab[i];
	for (j=0; j<row.length; ++j)
		{
		tab[i][j] = ENG.db.values[row[j]] ? ENG.db.values[row[j]] : '';
		}
	}
return tab;
}

ENG.func.renderTable = function(tab, table_class)
{
var i, j, tbody, thead, row, rows, tr_class, id;
tbody = '';
var sss = '';
for (i=0; i<tab.length; i++)
	{
//if (i>30) break;
	row = tab[i];
	tr_class = '';
	id = row[0] * 1;
	if (EE.query.length>0)
		{
//sss+= id;
//		for (j=0; j<EE.query.length; j++)
		for (j=1; j<EE.query.length; j++)	//no-edit
			{
//sss+= ' ' + EE.query[j].row_id
			if (id==EE.query[j].row_id)
				{tr_class = ' class="q"'; break;}
			}
//sss+= '<br>' 
		}
//	tbody += "\n"+'<tr'+ tr_class +' title="'+ id +'">';
	tbody += "\n"+'<tr'+ tr_class +'>';	//no-edit
//	tbody += '<th>'+i+'<\/th>';
//	for (j=0; j<row.length; j++)
	for (j=1; j<row.length; j++)	//no-edit
		{
		tbody += '<td>' + row[j] + '<\/td>';
		}
	tbody += '<\/tr>';
	}
//tbody+= '<pre>'+sss+'</pre>';
//if (tbody!='')
//	{
	thead  = "\n"+'<tr>';
	row = ENG.db.keys;
//	thead += '<th>&nbsp;<\/th>';
//	for (i=1; i<row.length; i++)
	for (i=1; i<row.length; i++) //no-edit
		{
		thead += render(ENG.tpl.table_th,{key:i,value:row[i]});
//'<th class="filter"><span onclick="ENG.func.filterOpenClick(this,'+i+');">[+] ' + row[i] + '<\/span><\/th>';
		}
	thead += '<\/tr>';
//	}
//return '<table class="' + table_class + '" onclick="EE.func.updateColumnClick(event);"><thead>' + thead + '<\/thead><tbody>' + tbody + '<\/tbody><\/table>';
return '<table class="' + table_class + '"><thead>' + thead + '<\/thead><tbody>' + tbody + '<\/tbody><\/table>'; //no-edit
//return '';
}






function newWindowPlainText(name, data)
{
var win, doc;
win = window.open('', name, '');//data:text/plain;
//win.location.href='#zasuvky_bn13_vyber.csv'; // pokus o zmenu title, url, neuspesny
doc = win.document;
doc.write('<plaintext>'+data); // FF v source tag ukazuje, ale pri ulozeni do souboru nee.
doc.close();
}

function class_csv(csv)
{
var i;
this.csv = {
	sep_row   : "\n",
	sep_col   : ';',
	enclosure : '"',
	escape    : '"'
	}
if (isExist(csv) && isObject(csv))
	{
	for (i in this.csv)
		{
		this.csv[i] = isSet(csv,i) ? csv[i] : this.csv[i];
		}
	}
this.escapeCsvValue = function(str)
	{
	var reg, spc, repl, csv;
	csv = this.csv;
	spc = '(['+escapeRegexp(csv.enclosure)+'])';
	re  = new RegExp(spc,'g');
	str = str + ''; //convert to string
	str = str.replace(re,csv.escape+'$1');
	spc = '['+escapeRegexp(csv.sep_col)+escapeRegexp(csv.sep_row)+']';
	re  = new RegExp(spc,'g');
	str = str.search(re)!=-1 ? csv.escape + str + csv.escape : str;
	// ignore RFC 4180
	return str;
	}
this.export = function(arr)
	{
	var i, row, csv, out;
	csv = this.csv;
	out = [];
	for (i=0; i<arr.length; ++i)
		{
		out[i] = [];
		row = arr[i];
		for (j=0; j<row.length; ++j)
			{
			out[i][j] = this.escapeCsvValue(row[j]);
			}
		out[i] = out[i].join(csv.sep_col);
		}
	return out.join(csv.sep_row);
	}
}
CSV = new class_csv(null);


ENG.func.exportCsv = function()
{
//str = "ah\"oj";
//str = "ah\n\
//oj";
//str = "ah;oj";
//str = "ahoj";
//str = ENG.func.escapeCsvValue(str);
//alert(str)
var tab;
tab = ENG.func.doFilters();
newWindowPlainText('csv_file',CSV.export(tab));
}




ENG.func.fsConvert = function(arr)
{
var arr2, i, str;
arr2 = [];
if (isArray(arr))
	{
	for (i=0;i<arr.length;i++)
		{
		arr2[arr2.length] = "{col:" + arr[i].col + ", type:'" + arr[i].type + "', order:'" + arr[i].order + "'}";
		}
	}
str = (arr2.length>0) ? "\n"+arr2.join(",\n") : '';
return '[' + str + "\n]";	// + [arr2.length, arr.length].join('|')
}

ENG.func.fsConvertBack = function(str)
{
try {eval(str);} catch (e) {return [];}
return eval(str) || [];
}

ENG.func.fsSelect = function()
{
ENG.obj.fs_area.value = ENG.func.fsConvert(ENG.fs.data);
}

ENG.func.fsUpdate = function()
{
ENG.fs.data = ENG.func.fsConvertBack(ENG.obj.fs_area.value);
toggle(ENG.obj.fs,false);
ENG.func.tableShow();
}

ENG.func.fsExample = function()
{
ENG.obj.fs_area.value = ENG.func.fsConvert(ENG.fs.data_example);
//ENG.func.fsUpdate();
}

ENG.func.fsOpenClick = function()
{
toggle(ENG.obj.fs);
ENG.func.ipShow();
ENG.func.fsSelect();
}

ENG.func.fsCreate = function(obj,param,data)
{
var i, str, tpl0, tpl1;
tpl0 = ENG.tpl.fs0;
tpl1 = ENG.tpl.fs1;
str = '';
for (i=0; i<data.length; i++)
	{
	str += render(tpl0,data[i]);
	}
param.data = str;
obj.innerHTML = render(tpl1,param);
}

ENG.func.fsCreateAll = function()
{
var i, data1, data2, out;
out = ['','',''];
data1 = ENG.db.keys;
data2 = [];
for (i=0;i<data1.length;i++)
	{
	data2[data2.length] = {value:i, text:data1[i], check:''};
	}
ENG.func.fsCreate(ENG.obj.fs_select[0], {id:'fs_select_0', name:'fs_select_0'}, data2);
data1 = compare_func.asc;
data2 = [];
for (i in data1)
	{
	data2[data2.length] = {value:i, text:i, check:''};
	}
//data2.sort( function(a,b){return a.text>b.text;} );
ENG.func.fsCreate(ENG.obj.fs_select[1], {id:'fs_select_1', name:'fs_select_1'}, data2);
data1 = compare_func;
data2 = [];
for (i in data1)
	{
	data2[data2.length] = {value:i, text:i, check:''};
	}
//data2.sort( function(a,b){return a.text>b.text;} );
ENG.func.fsCreate(ENG.obj.fs_select[2], {id:'fs_select_2', name:'fs_select_2'}, data2);
}

ENG.func.fsAdd = function()
{
arr = {col: getSel(objGet('fs_select_0')) * 1, type:getSel(objGet('fs_select_1')), order:getSel(objGet('fs_select_2')) };
ENG.fs.data = ENG.func.fsConvertBack(ENG.obj.fs_area.value);
ENG.fs.data[ENG.fs.data.length] = arr;
ENG.obj.fs_area.value = ENG.func.fsConvert(ENG.fs.data);
}

//[+] filtry sloupce aktivni / vypnuto serazeni aktivni radky aktivni qqq 

ENG.tpl.ip = {};
ENG.tpl.ip.all = 'Filtry: {filtry}';
ENG.tpl.ip.butt = '<span class="butt" onclick="{onclick}">{text} {stav}</span>';

ENG.func.ipShow = function()
{
//ENG.TPL.ip.fw = 'sloupce'
//ENG.TPL.ip.fs = 'serazeni'
//ENG.TPL.ip.fr = 'radky'
//ENG.TPL.ip.q = 'query'
if (ENG.obj.panel_info)
	{
	tpl  = ENG.tpl.ip;
	stav = ['<span style="color:#d00;">vypnuto<\/span>','<span style="color:#080;">zapnuto<\/span>'];
	str  = '';
	s = ENG.fw.data.length == 0 ? 0 : 1;
	str += render(tpl.butt,{text:'sloupce'  ,stav:stav[s],onclick:'alert(ENG.fw.data.toSource());'}) + ', ';
	s = ENG.fs.data.length == 0 ? 0 : 1;
	str += render(tpl.butt,{text:'serazeni' ,stav:stav[s],onclick:'ENG.func.fsOpenClick();'}) + ', ';
	s = !(ENG.filters_rows.start==0 && ENG.filters_rows.count==ENG.db.map.length) == 0 ? 0 : 1;
	str += render(tpl.butt,{text:'radky',stav:stav[s],onclick:'ENG.func.frOpenClick();'}) + ', ';
	s = EE.query.length == 0 ? 0 : 1;
	str += render(tpl.butt,{text:'query'    ,stav:stav[s],onclick:"EE.func.queryShow();"}) + ' | ';
	str += render(tpl.butt,{text:'ExportCsv',stav:''     ,onclick:"ENG.func.exportCsv();"}) + ', ';
	str += render(tpl.butt,{text:'ExportSql',stav:''     ,onclick:"EE.func.exportSql();"});
	ENG.obj.panel_info.innerHTML = render(tpl.all,{filtry:str});
	}
}

//-------------

function inArray(arr,val)
{
var i;
for (i=0; i<arr.length; i++)
	{
	if (arr[i] == val)
		{return i;}
	}
return false;
}

//-------------

//alert(db_map[0].length)
EE = {};	// edit engine
EE.obj = {};
EE.obj = ENG.obj;
EE.db  = {};
EE.db  = ENG.db;
EE.query = [];
EE.func = {};
EE.editmode = 1;
EE.update = {};
EE.tpl = {};
//EE.tpl.input = '<input type="text" value="{value}" onblur="EE.func.updateColumnClose(this);" class="coledit">';
EE.tpl.input = '<input type="text" value="{value}" class="coledit">';	//no-edit
//EE.func.dbValueFind = function(val)
//{
//for (i=0; i<EE.db.values.length; i++)
//	{
//	if (EE.db.values[i] == val)
//		{return key;}
//	}
//return false;
//}

//alert(EE.query.toSource())

EE.func.queryShow = function()
{
var i, str;
str = '';
for (i=0;i<EE.query.length;i++)
	{str += EE.query[i].toSource()+"\n";}
alert(str);
}

EE.func.queryFind = function(id)
{
var i;
for (i=0;i<EE.query.length;i++)
	{if (EE.query[i].row_id==id) {return i;}}
return i;
}

//EE.func.queryInsert = function(data)
//{
//EE.query[EE.query.length] = data;
//}

EE.func.queryUpdate = function(id, data)
{
EE.query[id] = data;
}

EE.func.queryAdd = function(data)
{
var id, i, row0, row1, bool;
id = EE.func.queryFind(data.row_id);
//alert(id,data.row_id)
if (data.type=='update' && isSet(EE.query,'type')) {data.type = EE.query[id].type;}	// nesmi se prepsat 'insert'
row0 = EE.db.map[data.row_id];
row1 = data.row;
bool = false;
//alert(row0+"\n"+row1)
for (i=0;i<row1.length;i++)	// check changes
	{if (row0[i]!=row1[i]) {bool = true; break;}}
if (bool==true)
	{
	EE.func.queryUpdate(id, data);
	}
}

EE.func.exportSql = function()
{
var out, i, j, row, data, query;
out = [];
for (i=0;i<EE.query.length;i++)
	{
	query = EE.query[i];
	data = query.row;
	row = [];
	row[row.length] = query.type;
	row[row.length] = query.row_id + ''; // to string
	for (j=0;j<data.length;j++)
		{
		row[row.length] = ENG.db.values[data[j]] ? ENG.db.values[data[j]] : '';
		}
	out[i] = row;
	}
newWindowPlainText('sql_data',CSV.export(out));
}

EE.func.dbFindAddValue = function(col_id,val)
{
var key;
key = inArray(EE.db.values, val);
if (key===false)
	{
	key = EE.db.values.length;
	EE.db.values[key] = val;
	EE.db.filters[col_id][EE.db.filters[col_id].length] = key;
	}
return key;
}

EE.func.dbSelectValues = function(id)
{
var i, row, out;
row = EE.db.map[id];
out = [];
for (i=0; i<row.length; j++)
	{
	out[i] = ENG.db.values[row[i]] ? ENG.db.values[row[i]] : '';
	}
return out;
}

EE.func.dbInsert = function(row)
{
var out, i, bool, key, id;
out = [];
for (i=0;i<row.length;i++)
	{
	out[i] = EE.func.dbFindAddValue(row[i]);
	}
id = EE.db.map.length;
EE.func.queryAdd({row_id:id, row:out, type:'insert'});
EE.db.map[id] = out;
ENG.init();
}

EE.func.dbUpdate = function(id, row)
{
var out, i, bool, key, id;
//out = [];
bool = false;
//for (i=0;i<row.length;i++)
//	{
//	out[i] = EE.func.dbFindAddValue(row[i]);
//	}
//alert(out)
EE.func.queryAdd({row_id:id, row:row, type:'update'});
EE.db.map[id] = row;
//EE.func.queryAdd([id, row, 'update']);
//EE.queryAdd('update', id, row);
ENG.func.init();
ENG.func.tableShow();
}

EE.func.dbDelete = function(id)
{
//EE.func.queryAdd([id, null, 'delete']);
EE.func.queryAdd({row_id:id, row:null, type:'delete'});
EE.db.map[id] = [];
}

EE.func.updateColumnClick = function(event)
{
event  = event || window.event;
target = event.target || event.srcElement;
//alert(target.nodeName)
if (target.nodeName=='TD' && EE.editmode==1)
	{
	EE.func.updateColumnOpen(target);
	//alert(id);
	}
}

EE.func.updateColumnOpen = function (target)
{
var tr, row, col, input;
tr  = target.parentNode;
row_id = tr.title * 1;
col_id = target.cellIndex * 1;
if (EE.update.row_id!==row_id || EE.update.col_id!==col_id)
	{
	EE.func.updateColumnClose();
	EE.update.row_id = row_id;
	EE.update.col_id = col_id;
	EE.update.value = target.innerHTML;
	EE.update.td    = target;
	target.innerHTML = render(EE.tpl.input,EE.update);
	input = target.getElementsByTagName('INPUT')[0];
	input.focus();			// cursor to input
	//input.value = input.value;	// cursor to end
	input.selectionStart = input.selectionEnd = input.value.length; // cursor to end
	}
//alert([row,col])
}

EE.func.updateColumnReset = function()
{
EE.update.row_id = -1;
EE.update.col_id = -1;
EE.update.value = '';
EE.update.td    = null;
}

EE.func.updateColumnClose = function (el)
{
var id, value, row, row_id, col_id;
value = el ? el.value : EE.update.value;
if (EE.update.td)
	{
	value = trim(value);
//	EE.update.td.innerHTML = value;	 neni treba, protoze se prekresluje cela tabulka
	row_id = EE.update.row_id;
	col_id = EE.update.col_id;
	row = cloneArray1(EE.db.map[row_id]);
	row[col_id] = EE.func.dbFindAddValue(col_id,value);	// row undefined
//	EE.func.dbUpdate(EE.func.rowSelect(EE.update.row))
	EE.func.dbUpdate(row_id,row);
	ENG.func.ipShow();
	// sql update
//ENG.func.tableShow();
	}
EE.func.updateColumnReset();
//ENG.func.init();
}

EE.func.rowSelect = function(id)
{
/*
out = [];
tr = 
for (i=0;i<row.length;i++)
	{
	out[i] = EE.func.dbFindAddValue(row[i]);
	}
*/
}

// ---------------

var SS;
SS = {};
SS.obj = {};
SS.obj.panel_search = objGet('panel_search');
SS.obj.search_cmp_type = 'search_cmp_type';
SS.tpl = {};
SS.tpl.td = "\n"+'\
<td class="col{key1}">\
<label for="{id}">{text}<\/label><br>\
<input type="text" name="{name}" id="{id}" value="{value}" onkeyup="SS.func.search(this,{key1});">\
<\/td>\
';
SS.tpl.radio = "\n"+'\
<label><input type="radio" name="{name}" id="{id}" value="{value}" onclick="SS.func.searchCmpType(this);" {checked}> {text}<\/label>\
';
//{radio}<br>\
SS.tpl.table = "\n"+'\
<table>\
<tr>\
{tbody}\
<\/tr>\
<\/table>\
';
SS.f = {};
//SS.f.data_out = ENG.fw.data;
SS.f.words_index = db_filters;
SS.f.words_value = db_values;
SS.data = {};
SS.data.cmp = 1;
SS.data.phrase = '';
SS.data.key1 = '';
SS.data.key2 = '';
SS.func = {};
SS.func.searchCmpType = function(inp)
	{
	if (inp && inp.checked)
		{
		SS.f.search_cmp_type = inp.value * 1;
		SS.func.searchPhrase();
		}
	}
SS.func.init = function()
	{
	var out,td,radio,i,j, row;
	out   = '';
	td    = '';
	radio = '';
	row   = ENG.db.keys;
//	for (i=0; i<row.length; i++)
	cols = [1,2,5];
	for (j=0; j<cols.length; j++)	//no-edit
		{
		i = cols[j];
		td += render(SS.tpl.td,{'key1':i,'name':'search_'+i,'id':'search_'+i,'value':'','text':row[i]});
		}
	name = SS.obj.search_cmp_type;
	i = 0;
//	radio += render(SS.tpl.radio,{'name':name,'id':name+i,'value':i,'text':'zacatek vsech slov'   ,'checked':'checked="checked"'}); i++;
//	radio += render(SS.tpl.radio,{'name':name,'id':name+i,'value':i,'text':'zacatek prvniho slova','checked':''});
	out = render(SS.tpl.table,{'radio':radio,'tbody':td});
	SS.obj.panel_search.innerHTML = out;
	ENG.fw.multi_cols = [[1],[2,3,4],[5,6,7,8]];
	}
SS.func.searchCmp2 = function(a,b)
	{
	return a.indexOf(b)===0 ? -1 : 1;
	}
SS.func.searchCmp1 = function(a,b)
	{
	var pos = a.indexOf(b);
//alert(pos)
/*
if (pos>0 && /[^a-z]/.test(SS.func.clear(a.charAt(pos-1))))
alert([
pos,
a.charAt(pos-1),
SS.func.clear(a.charAt(pos-1)),
/[^a-z]/.test(SS.func.clear(a.charAt(pos-1))),
a,
b
]);
*/
	return pos===0 || (pos>0 && /[^a-z]/.test(a.charAt(pos-1))) ? -1 : 1;	//SS.func.clear(
	}
SS.func.clear = function(str)
	{
	var a,b,c,out,i;
	a = "徜栾殪礤掘篝鲟殱鵀聊认商团家釉掷妽谫茌貛";
	b = "aacdeeillnooorstuuuyrzAACDEEILLNOOORSTUUUYRZ";
	out = '';
	for(i = 0; i < str.length; i++)
		{
		c = str.charAt(i);
		if (a.indexOf(c) != -1)
			{
			c = b.charAt(a.indexOf(c));
			}
		out += c;
		}
	out = out.toLowerCase();
	return out;
	} 
SS.func.search = function(inp,key1)
	{
	SS.data.phrase = SS.func.clear(inp.value);
	SS.data.key1   = key1;
	SS.func.searchPhrase();
	}
/*
ENG.func.fwCheckValue = function(key1, key2, value)
{
if (!isSet(ENG.fw.data,key1))
	{
	ENG.fw.data[key1] = [];
	}
return value && isSet(ENG.db.filters[key1],key2) ? ENG.db.filters[key1][key2];
}

ENG.func.fwUpdateFilter = function(key1, key2, bool)
{
if (!isSet(ENG.fw.data,key1))
	{
	ENG.fw.data[key1] = [];
	}
ENG.fw.data[key1][key2] = bool && isSet(ENG.db.filters[key1],key2) ? ENG.db.filters[key1][key2] : null;
}
*/
SS.func.searchPhrase = function()
	{
	var phrase, word, key1, word_all,i,bool, func, multi_cols, col;
	key1 = SS.data.key1;
	if (!isSet(SS.f.words_index,key1)) {return;}
	func     = SS.data.cmp==1 ? SS.func.searchCmp1 : SS.func.searchCmp0;
	phrase   = SS.data.phrase;
	multi_cols = [key1];
	if (key1==2) {multi_cols = [2,3,4];}
	if (key1==5) {multi_cols = [5,6,7,8];}
	for (j=0;j<multi_cols.length;j++)
		{
		bool = true;
		col      = multi_cols[j];
		word_all = SS.f.words_index[col];
		for (i=0;i<word_all.length;i++)
			{
			word = word_all[i];
			word = SS.f.words_value[word];
			word = SS.func.clear(word);
			bool = func(word,phrase)>0;
			ENG.func.fwUpdate(col,i,bool);
//ENG.func.filterWords = function(tab,filters,multi_cols)
			}
		ENG.fw.key = col;
		ENG.func.fwCreate(false);
		}
	ENG.func.tableShow();
	}

// --------------



perf = new class_perf();
EE.func.updateColumnReset();

ENG.func.init();
ENG.func.tableShow();

SS.func.init();
