// if two digit year input dates after this year considered 20 century.
var NUM_CENTYEAR = 30;
// is time input control required by default
var BUL_TIMECOMPONENT = false;
// are year scrolling buttons required by default
var BUL_YEARSCROLL = true;
var calendars = [];
var RE_NUM = /^\-?\d+$/;


var clock24_lang = new Array();
clock24_lang["en"] = ['en','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec',
'Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
clock24_lang["ru"] = ['ru','\u042F\u043D\u0432','\u0424\u0435\u0432','\u041C\u0430\u0440','\u0410\u043F\u0440',
'\u041C\u0430\u0439','\u0418\u044E\u043D','\u0418\u044E\u043B','\u0410\u0432\u0433',
'\u0421\u0435\u043D','\u041E\u043A\u0442','\u041D\u043E\u044F','\u0414\u0435\u043A',
'\u0412\u0441','\u041F\u043D','\u0412\u0442','\u0421\u0440','\u0427\u0442','\u041F\u0442','\u0421\u0431'];

var clock24_dst = new Array(
/* 0  */ [ [0,7,3,0,7,10,60], [] ],	//CIS					  //Europe
/* EU */ [ [0,7,3,0,7,10,60], ["RU","AZ","AM","BY","MD","UA","AT","AL","AD","BE","BG","BA","VA","GB","HU","DE","GR","DK","IE","ES","IT","CY","LV","LT","LI","LU","MT","MK","MC","NL","NO","PL","PT","RO","SM","CS","SK","SI","TR","FI","FR","HR","CZ","CH","SE","EE"] ],
/* US */ [ [2,7,3,1,7,11,60], ["US","CA"] ],
/* MX */ [ [1,7,4,0,7,10,60], ["MX"] ],
/* CU */ [ [3,7,3,0,7,10,60], ["CU"] ],
/* IR */ [ [4,5,3,3,6,9,60],  ["IR"] ],
/* IL */ [ [0,5,3,1,7,10,60], ["IL"] ],
/* EG */ [ [0,5,4,0,4,8,60],  ["EG"] ],
//southern hemisphere
/* AU */ [ [1,7,10,1,7,4,60], ["AU"] ],
/* NZ */ [ [0,7,9,1,7,4,60],  ["NZ"] ],
/* CL */ [ [2,7,10,0,7,3,60], ["CL"] ],
/* BR */ [ [1,7,11,0,7,2,60], ["BR"] ]
);

function clock24(p,tz,fmt,lang)
{
	this.p = p;
	if(tz == 999) {
		var now = new Date();
		tz = -1 * now.getTimezoneOffset();
	}
	this.tz = tz;
	if(fmt=='') fmt = '%hh:%nn:%ss';
	this.fmt = fmt;
	this.refresh = clock24_refresh;
	this.format = clock24_format;
	this.daylight = clock24_daylight;
	this.dstdata = 0;
	this.dst1 = 0;
	this.dst2 = 0;
	this.dsttype = 0;

	if(!clock24_lang[lang]) lang = "en";
	this.lang = lang;

	this.clock24_m = new Array();
	this.clock24_m[1] = clock24_lang[lang][1]; this.clock24_m[2] = clock24_lang[lang][2];
	this.clock24_m[3] = clock24_lang[lang][3]; this.clock24_m[4] = clock24_lang[lang][4];
	this.clock24_m[5] = clock24_lang[lang][5]; this.clock24_m[6] = clock24_lang[lang][6];
	this.clock24_m[7] = clock24_lang[lang][7]; this.clock24_m[8] = clock24_lang[lang][8];
	this.clock24_m[9] = clock24_lang[lang][9]; this.clock24_m[10] = clock24_lang[lang][10];
	this.clock24_m[11] = clock24_lang[lang][11]; this.clock24_m[12] = clock24_lang[lang][12];

	this.clock24_w = new Array();
	this.clock24_w[0] = clock24_lang[lang][13]; this.clock24_w[1] = clock24_lang[lang][14];
 	this.clock24_w[2] = clock24_lang[lang][15]; this.clock24_w[3] = clock24_lang[lang][16];
	this.clock24_w[4] = clock24_lang[lang][17]; this.clock24_w[5] = clock24_lang[lang][18];
	this.clock24_w[6] = clock24_lang[lang][19]; 

	window.setInterval("clock24_"+p+".refresh()", 1000); 
}

function clock24_refresh()
{
	var now = new Date();
	now = new Date( now.getTime() + this.tz * 60000);
	if(this.dst1 && this.dsttype) {
		if(now.getTime() > this.dst1 || now.getTime() < this.dst2)
			now = new Date( now.getTime() + this.dstdata*60000 );
	} else if(this.dst1) {
		if(now.getTime() > this.dst1 && now.getTime() < this.dst2)
			now = new Date( now.getTime() + this.dstdata*60000 );
	}
	
	document.getElementById('clock24_'+this.p).innerHTML = this.format(now, this.fmt);
}

function clock24_format(now, clock24_f)
{
	var d = now.getUTCDate(); var dd = d; if(d<10) dd = '0'+d;
	var m = now.getUTCMonth() + 1;	var mm = m; if(m<10) mm = '0'+m;
	var yyyy = now.getUTCFullYear(); var yy = yyyy - 2000; if(yy<10) yy = '0'+yy;

	var h = now.getUTCHours(); var hh = h; if(h<10) hh='0'+h;
	var H = h % 12; if(H==0) H = 12; var HH = H; if(H<10) HH='0'+H;
	var n = now.getUTCMinutes(); var nn = n; if(nn<10) nn='0'+n;
	var s = now.getUTCSeconds(); var ss = s; if(ss<10) ss='0'+s;

	var w = now.getUTCDay(); W = this.clock24_w[w];
	var M = this.clock24_m[m];

	var p = 'am'; if(h >= 12) p = 'pm'; var P = 'AM'; if(h >= 12) P = 'PM';

	var s = new String(clock24_f);
	s = s.replace( new RegExp("%dd"), dd);
	s = s.replace( new RegExp("%d"), d);
	s = s.replace( new RegExp("%mm"), mm);
	s = s.replace( new RegExp("%m"), m);
	s = s.replace( new RegExp("%yyyy"), yyyy);
	s = s.replace( new RegExp("%yy"), yy);
	s = s.replace( new RegExp("%hh"), hh);
	s = s.replace( new RegExp("%h"), h);
	s = s.replace( new RegExp("%nn"), nn);
	s = s.replace( new RegExp("%n"), n);
	s = s.replace( new RegExp("%ss"), ss);
	s = s.replace( new RegExp("%s"), s);
	s = s.replace( new RegExp("%HH"), HH);
	s = s.replace( new RegExp("%H"), H);

	s = s.replace( new RegExp("%W"), W);
	s = s.replace( new RegExp("%M"), M);

	s = s.replace( new RegExp("%p"), p);
	s = s.replace( new RegExp("%P"), P);
	
	return s.toString();
}

function clock24_daylight(c)
{
	c = clock24_find_dst(c);
	if(!c) {
		this.dst1 = 0; this.dst2 = 0;
		return;
	}
	dd = clock24_dst[c][0];
	d = clock24_byweekday(dd[0],dd[1],dd[2]-1);
	d.setUTCHours(2,0,0,0);
	this.dst1 = d.getTime();
	d = clock24_byweekday(dd[3],dd[4],dd[5]-1);
	d.setUTCHours(3,0,0,0);
	this.dst2 = d.getTime();
	if(this.dst1 > this.dst2) this.dsttype = 1;
	this.dstdata = dd[6];
}

function clock24_byweekday(pos,w,mon)
{
	// pos: 0-last weekday, 1-first weekday, 2-second...
	// w=[1..7],7-sun
	// mon=[0..11]
	var now = new Date();
	now.setUTCMonth(mon, 1);
	w1 = 1 + Math.abs(w - now.getUTCDay());
	now.setUTCDate(w1);	//first needed weekday in month
	wn = 0;
	if(pos) wn = (pos-1)*7 + w1;
	else {
		for(i=2; i<=6; i++) {
			td = new Date(  now.getTime() + 7*i*86400*1000 );
			if(td.getUTCMonth() > mon) {
				wn = w1 + 7*(i-1);
				break;
			}
		}
	}
	now.setUTCDate(wn);
	return now;
}

function clock24_find_dst(c)
{
	if(!c) return;
	for(var i=0; i<clock24_dst.length; i++)
	{
		for(var j=0; j<clock24_dst[i][1].length; j++)
		{
			if(clock24_dst[i][1][j] == c) return i;
		}
	}
}


function calendar1(obj_target) {

	// assigning methods
	this.gen_date = cal_gen_date1;
	this.gen_time = cal_gen_time1;
	this.gen_tsmp = cal_gen_tsmp1;
	this.prs_date = cal_prs_date1;
	this.prs_time = cal_prs_time1;
	this.prs_tsmp = cal_prs_tsmp1;
	this.popup    = cal_popup1;

	// validate input parameters
	if (!obj_target)
		return cal_error("Error calling the calendar: no target control specified");
	if (obj_target.value == null)
		return cal_error("Error calling the calendar: parameter specified is not valid target control");
	this.target = obj_target;
	this.time_comp = BUL_TIMECOMPONENT;
	this.year_scroll = BUL_YEARSCROLL;

	// register in global collections
	this.id = calendars.length;
	calendars[this.id] = this;
}

function cal_popup1 (str_datetime) {
	if (str_datetime)
		this.dt_current = this.prs_tsmp(str_datetime);
	else
		this.dt_selected = this.dt_current = this.prs_tsmp(this.target.value);

	if (!this.dt_current) return;

	var obj_calwindow = window.open(
		'calendar.html?id=' + this.id + '&s=' + this.dt_selected.valueOf() + '&c=' + this.dt_current.valueOf(),
		'Calendar', 'width=200,height=' + (this.time_comp ? 215 : 190) +
		',status=no,resizable=no,top=200,left=200,dependent=yes,alwaysRaised=yes'
	);
	obj_calwindow.opener = window;
	obj_calwindow.focus();
}

// timestamp generating function
function cal_gen_tsmp1 (dt_datetime) {
	return(this.gen_date(dt_datetime) + ' ' + this.gen_time(dt_datetime));
}

// date generating function
function cal_gen_date1 (dt_datetime) {
	return (
		(dt_datetime.getDate() < 10 ? '0' : '') + dt_datetime.getDate() + "-"
		+ (dt_datetime.getMonth() < 9 ? '0' : '') + (dt_datetime.getMonth() + 1) + "-"
		+ dt_datetime.getFullYear()
	);
}
// time generating function
function cal_gen_time1 (dt_datetime) {
	return (
		(dt_datetime.getHours() < 10 ? '0' : '') + dt_datetime.getHours() + ":"
		+ (dt_datetime.getMinutes() < 10 ? '0' : '') + (dt_datetime.getMinutes()) + ":"
		+ (dt_datetime.getSeconds() < 10 ? '0' : '') + (dt_datetime.getSeconds())
	);
}

// timestamp parsing function
function cal_prs_tsmp1 (str_datetime) {
	// if no parameter specified return current timestamp
	if (!str_datetime)
		return (new Date());

	// if positive integer treat as milliseconds from epoch
	if (RE_NUM.exec(str_datetime))
		return new Date(str_datetime);

	// else treat as date in string format
	var arr_datetime = str_datetime.split(' ');
	return this.prs_time(arr_datetime[1], this.prs_date(arr_datetime[0]));
}

// date parsing function
function cal_prs_date1 (str_date) {

	var arr_date = str_date.split('-');

	if (arr_date.length != 3) return cal_error ("Неверный формат даты: '" + str_date + "'.\nФормат даты должен быть вида ДД-ММ-ГГГГ.");
	if (!arr_date[0]) return cal_error ("Invalid date format: '" + str_date + "'.\nNo day of month value can be found.");
	if (!RE_NUM.exec(arr_date[0])) return cal_error ("Invalid day of month value: '" + arr_date[0] + "'.\nAllowed values are unsigned integers.");
	if (!arr_date[1]) return cal_error ("Invalid date format: '" + str_date + "'.\nNo month value can be found.");
	if (!RE_NUM.exec(arr_date[1])) return cal_error ("Invalid month value: '" + arr_date[1] + "'.\nAllowed values are unsigned integers.");
	if (!arr_date[2]) return cal_error ("Invalid date format: '" + str_date + "'.\nNo year value can be found.");
	if (!RE_NUM.exec(arr_date[2])) return cal_error ("Invalid year value: '" + arr_date[2] + "'.\nAllowed values are unsigned integers.");

	var dt_date = new Date();
	dt_date.setDate(1);

	if (arr_date[1] < 1 || arr_date[1] > 12) return cal_error ("Invalid month value: '" + arr_date[1] + "'.\nAllowed range is 01-12.");
	dt_date.setMonth(arr_date[1]-1);

	if (arr_date[2] < 100) arr_date[2] = Number(arr_date[2]) + (arr_date[2] < NUM_CENTYEAR ? 2000 : 1900);
	dt_date.setFullYear(arr_date[2]);

	var dt_numdays = new Date(arr_date[2], arr_date[1], 0);
	dt_date.setDate(arr_date[0]);
	if (dt_date.getMonth() != (arr_date[1]-1)) return cal_error ("Invalid day of month value: '" + arr_date[0] + "'.\nAllowed range is 01-"+dt_numdays.getDate()+".");

	return (dt_date)
}

// time parsing function
function cal_prs_time1 (str_time, dt_date) {

	if (!dt_date) return null;
	var arr_time = String(str_time ? str_time : '').split(':');

	if (!arr_time[0]) dt_date.setHours(0);
	else if (RE_NUM.exec(arr_time[0]))
		if (arr_time[0] < 24) dt_date.setHours(arr_time[0]);
		else return cal_error ("Invalid hours value: '" + arr_time[0] + "'.\nAllowed range is 00-23.");
	else return cal_error ("Invalid hours value: '" + arr_time[0] + "'.\nAllowed values are unsigned integers.");

	if (!arr_time[1]) dt_date.setMinutes(0);
	else if (RE_NUM.exec(arr_time[1]))
		if (arr_time[1] < 60) dt_date.setMinutes(arr_time[1]);
		else return cal_error ("Invalid minutes value: '" + arr_time[1] + "'.\nAllowed range is 00-59.");
	else return cal_error ("Invalid minutes value: '" + arr_time[1] + "'.\nAllowed values are unsigned integers.");

	if (!arr_time[2]) dt_date.setSeconds(0);
	else if (RE_NUM.exec(arr_time[2]))
		if (arr_time[2] < 60) dt_date.setSeconds(arr_time[2]);
		else return cal_error ("Invalid seconds value: '" + arr_time[2] + "'.\nAllowed range is 00-59.");
	else return cal_error ("Invalid seconds value: '" + arr_time[2] + "'.\nAllowed values are unsigned integers.");

	dt_date.setMilliseconds(0);
	return dt_date;
}

function cal_error (str_message) {
	alert (str_message);
	return null;
}

function ImageExpander(oThumb, sImgSrc)
{
	// store thumbnail image and overwrite its onclick handler.
	this.oThumb = oThumb;
	this.oThumb.expander = this;
	this.oThumb.onclick = function() { this.expander.expand(); }
	
	// record original size
	this.smallWidth = oThumb.offsetWidth;
	this.smallHeight = oThumb.offsetHeight;	

	this.bExpand = true;
	this.bTicks = false;
	
	// self organized list
	if ( !window.aImageExpanders )
	{
		window.aImageExpanders = new Array();
	}
	window.aImageExpanders.push(this);

	// create the full sized image.
	this.oImg = new Image();
	this.oImg.expander = this;
	this.oImg.onload = function(){this.expander.onload();}
	this.oImg.src = sImgSrc;
}

ImageExpander.prototype.onload = function()
{
	this.oDiv = document.createElement("div");
	document.body.appendChild(this.oDiv);
	this.oDiv.appendChild(this.oImg);
	this.oDiv.style.position = "absolute";
	this.oDiv.expander = this;
	this.oDiv.onclick = function() {this.expander.toggle();};
	this.oImg.title = "Click to reduce.";
	this.bigWidth = this.oImg.width;
	this.bigHeight = this.oImg.height;
	
	if ( this.bExpand )
	{
		this.expand();
	}
	else
	{
		this.oDiv.style.visibility = "hidden";
		this.oImg.style.visibility = "hidden";
	}
}
ImageExpander.prototype.toggle = function()
{
	this.bExpand = !this.bExpand;
	if ( this.bExpand )
	{
		for ( var i in window.aImageExpanders )
			if ( window.aImageExpanders[i] !== this )
				window.aImageExpanders[i].reduce();
	}
}
ImageExpander.prototype.expand = function()
{
	// set direction of expansion.
	this.bExpand = true;

	// set all other images to reduce
	for ( var i in window.aImageExpanders )
		if ( window.aImageExpanders[i] !== this )
			window.aImageExpanders[i].reduce();

	// if not loaded, don't continue just yet
	if ( !this.oDiv ) return;
	
	// hide the thumbnail
	this.oThumb.style.visibility = "hidden";
	
	// calculate initial dimensions
	this.x = this.oThumb.offsetLeft;
	this.y = this.oThumb.offsetTop;
	this.w = this.oThumb.clientWidth;
	this.h = this.oThumb.clientHeight;
	
	this.oDiv.style.left = this.x + "px";
	this.oDiv.style.top = this.y + "px";
	this.oImg.style.width = this.w + "px";
	this.oImg.style.height = this.h + "px";
	this.oDiv.style.visibility = "visible";
	this.oImg.style.visibility = "visible";
	
	// start the animation engine.
	if ( !this.bTicks )
	{
		this.bTicks = true;
		var pThis = this;
		window.setTimeout(function(){pThis.tick();},25);	
	}
}
ImageExpander.prototype.reduce = function()
{
	// set direction of expansion.
	this.bExpand = false;
}
ImageExpander.prototype.tick = function()
{
	// calculate screen dimensions
	var cw = document.body.clientWidth;
	var ch = document.body.clientHeight;
	var cx = document.body.scrollLeft + cw / 2;
	var cy = document.body.scrollTop + ch / 2;

	// calculate target
	var tw,th,tx,ty;
	if ( this.bExpand )
	{
		tw = this.bigWidth;
		th = this.bigHeight;
		if ( tw > cw )
		{
			th *= cw / tw;
			tw = cw;
		}	
		if ( th > ch )
		{
			tw *= ch / th;
			th = ch;
		}
		tx = cx - tw / 2;
		ty = cy - th / 2; 
	}
	else
	{
		tw = this.smallWidth;
		th = this.smallHeight;
		tx = this.oThumb.offsetLeft;
		ty = this.oThumb.offsetTop;
	}	
	// move 5% closer to target
	var nHit = 0;
	var fMove = function(n,tn) 
	{
		var dn = tn - n;
		if ( Math.abs(dn) < 3 )
		{
			nHit++;
			return tn;
		}
		else
		{
			return n + dn / 10;
		}
	}
	this.x = fMove(this.x, tx);
	this.y = fMove(this.y, ty);
	this.w = fMove(this.w, tw);
	this.h = fMove(this.h, th);
	
	this.oDiv.style.left = this.x + "px";
	this.oDiv.style.top = this.y + "px";
	this.oImg.style.width = this.w + "px";
	this.oImg.style.height = this.h + "px";

	// if reducing and size/position is a match, stop the tick	
	if ( !this.bExpand && (nHit == 4) )
	{
		this.oImg.style.visibility = "hidden";
		this.oDiv.style.visibility = "hidden";
		this.oThumb.style.visibility = "visible";

		this.bTicks = false;
	}
	
	if ( this.bTicks )
	{
		var pThis = this;
		window.setTimeout(function(){pThis.tick();},25);
	}
}

