/*
Credits:
Date.getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.meanfreepath.com
CalendarDateSelect was developed by Tim Charper at http://code.google.com/p/calendardateselect
Modifications, fixes, and localization by Koodiviidakko Oy at http://www.viidakko.fi/
*/

Element.addMethods({
	purgeChildren: function(element) { $A(element.childNodes).each(function(e){$(e).remove();}); },
	build: function(element, type, options, style) {
		var newElement = Element.buildAndAppend(type, options, style);
		element.appendChild(newElement);
		return newElement;
	}
});

Element.buildAndAppend = function(type, options, style) {
	var e = $(document.createElement(type));
	$H(options).each(function(pair) { e[pair.key] = pair.value });
	if (style) e.setStyle(style);
	return e;
};

(function() {
	Date.oneDay = 86400000;
	Date.language = $(document.documentElement).readAttribute('lang') || 'en';
	if (Date.language == 'fi') {
		Date.weekdays = $w('Ma Ti Ke To Pe La Su');
		Date.months = $w('Tammi Helmi Maalis Huhti Touko KesÃ¤ HeinÃ¤ Elo Syys Loka Marras Joulu');
		Date.dowOffset = 1;
		Date.weekNumberName = 'vko';
	} else {
		Date.weekdays = $w("S M T W T F S");
		Date.dowOffset = 0;
		Date.months = $w("January February March April May June July August September October November December");
		Date.weekNumberName = 'wk';
	}
})();

Date.padded2 = function(hour) { var padded2 = parseInt(hour, 10); if (hour < 10) padded2 = "0" + padded2; return padded2; }
Date.prototype.getPaddedMinutes = function() { return Date.padded2(this.getMinutes()); }
Date.prototype.getAMPMHour = function() { var hour = this.getHours(); return (hour == 0) ? 12 : (hour > 12 ? hour - 12 : hour ) }
Date.prototype.getAMPM = function() { return (this.getHours() < 12) ? "AM" : "PM"; }
Date.prototype.stripTime = function() { return new Date(this.getFullYear(), this.getMonth(), this.getDate());};
Date.prototype.daysDistance = function(compare_date) { return Math.round((compare_date - this) / Date.oneDay); };
Date.prototype.formatDate = function(format) {
	var month = (this.getMonth() + 1).toString();
	if (10 > month) month = "0" + month;
	var day = this.getDate().toString();
	if (10 > day) day = "0" + day;
	format = format.replace(/%d/, day);
	format = format.replace(/%m/, month);
	format = format.replace(/%Y/, this.getFullYear().toString());
	format = format.replace(/%y/, this.getFullYear().toString().substr(2, 2));

	return format;
}
Date.prototype.getWeek = function () {


var newYear = new Date(this.getFullYear(),0,1);
var day = newYear.getDay() - Date.dowOffset; //the day of week the year begins on
day = (day >= 0 ? day : day + 7);
var daynum = Math.floor((this.getTime() - newYear.getTime() -
(this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/Date.oneDay) + 1;
var weeknum;
//if the year starts before the middle of a week
if(day < 4) {
weeknum = Math.floor((daynum+day-1)/7) + 1;
if(weeknum > 52) {
nYear = new Date(this.getFullYear() + 1,0,1);
nday = nYear.getDay() - Date.dowOffset;
nday = nday >= 0 ? nday : nday + 7;
/*if the next year starts before the middle of
the week, it is week #1 of that year*/
weeknum = nday < 4 ? 1 : 53;
}
}
else {
weeknum = Math.floor((daynum+day-1)/7);
}
return weeknum;
};

Math.floor_to_interval = function(n, i) { return Math.floor(n/i) * i;}
window.f_height = function() { return( [window.innerHeight ? window.innerHeight : null, document.documentElement ? document.documentElement.clientHeight : null, document.body ? document.body.clientHeight : null].select(function(x){return x>0}).first()||0); }
window.f_scrollTop = function() { return ([window.pageYOffset ? window.pageYOffset : null, document.documentElement ? document.documentElement.scrollTop : null, document.body ? document.body.scrollTop : null].select(function(x){return x>0}).first()||0 ); }

SelectBox = Class.create();
SelectBox.prototype = {
  initialize: function(parent_element, values, html_options, style_options) {
	this.element = $(parent_element).build("select", html_options, style_options);
	this.populate(values);
  },
  populate: function(values) {
	this.element.purgeChildren();
	var that = this; $A(values).each(function(pair) { if (typeof(pair)!="object") {pair = [pair, pair]}; that.element.build("option", { value: pair[1], innerHTML: pair[0]}) });
  },
  setValue: function(value) {
	var e = this.element;
	var matched = false;
	$R(0, e.options.length - 1 ).each(function(i) { if(e.options[i].value==value.toString()) {e.selectedIndex = i; matched = true;}; } );
	return matched;
  },
  getValue: function() { return $F(this.element)}
}
CalendarDateSelect = Class.create();
CalendarDateSelect.prototype = {
  initialize: function(target_element, options) {
	this.target_element = $(target_element); // make sure it's an element, not a string
	if (!this.target_element) { alert("Target element " + target_element + " not found!"); return false;}
	if (this.target_element.tagName != "INPUT") this.target_element = this.target_element.down("INPUT")

	this.target_element.calendar_date_select = this;
	this.last_click_at = 0;
	// initialize the date control
	this.options = $H({
	  embedded: false,
	  popup: null,
	  time: false,
	  buttons: true,
	  clear_button: true,
	  year_range: 10,
	  close_on_click: null,
	  minute_interval: 5,
	  popup_by: this.target_element,
	  month_year: "dropdowns",
	  onchange: this.target_element.onchange,
	  valid_date_check: null
	}).merge(options || {});
	this.use_time = this.options.get("time");
	this.parseDate();
	this.callback("before_show")
	this.initCalendarDiv();
	if(!this.options.get("embedded")) {
	  this.positionCalendarDiv()
	  // set the click handler to check if a user has clicked away from the document
	  Event.observe(document, "mousedown", this.closeIfClickedOut_handler = this.closeIfClickedOut.bindAsEventListener(this));
	  Event.observe(document, "keypress", this.keyPress_handler = this.keyPress.bindAsEventListener(this));
	}
	this.callback("after_show")
  },
  positionCalendarDiv: function() {
	var above = false;
	var c_pos = this.calendar_div.cumulativeOffset(), c_left = c_pos[0], c_top = c_pos[1], c_dim = this.calendar_div.getDimensions(), c_height = c_dim.height, c_width = c_dim.width;
	var w_top = window.f_scrollTop(), w_height = window.f_height();
	var e_dim = $(this.options.get("popup_by")).cumulativeOffset(), e_top = e_dim[1], e_left = e_dim[0], e_height = $(this.options.get("popup_by")).getDimensions().height, e_bottom = e_top + e_height;

	if ( (( e_bottom + c_height ) > (w_top + w_height)) && ( e_bottom - c_height > w_top )) above = true;
	var left_px = e_left.toString() + "px", top_px = (above ? (e_top - c_height ) : ( e_top + e_height )).toString() + "px";

	this.calendar_div.style.left = left_px;  this.calendar_div.style.top = top_px;

	this.calendar_div.setStyle({visibility:""});

	// draw an iframe behind the calendar -- ugly hack to make IE 6 happy
	if(navigator.appName=="Microsoft Internet Explorer") this.iframe = $(document.body).build("iframe", {src: "javascript:false", className: "ie6_blocker"}, { left: left_px, top: top_px, height: c_height.toString()+"px", width: c_width.toString()+"px", border: "0px"})
  },
  initCalendarDiv: function() {
	if (this.options.get("embedded")) {
	  var parent = this.target_element.parentNode;
	  var style = {}
	} else {
	  var parent = document.body
	  var style = { position:"absolute", visibility: "hidden", left:0, top:0 }
	}
	this.calendar_div = $(parent).build('div', {className: "calendar_date_select"}, style);

	var that = this;
	// create the divs
	$w("top header body buttons footer bottom").each(function(name) {
	  eval("var " + name + "_div = that." + name + "_div = that.calendar_div.build('div', { className: 'cds_"+name+"' }, { clear: 'left'} ); ");
	});

	this.initHeaderDiv();
	this.initButtonsDiv();
	this.initCalendarGrid();
	this.updateFooter("&#160;");

	this.refresh();
	this.setUseTime(this.use_time);
  },
  initHeaderDiv: function() {
	var header_div = this.header_div;
	this.close_button = header_div.build("a", { innerHTML: "x", href:"#", onclick:function () { this.close(); return false; }.bindAsEventListener(this), className: "close" });
	this.next_month_button = header_div.build("a", { innerHTML: "&gt;", href:"#", onclick:function () { this.navMonth(this.date.getMonth() + 1 ); return false; }.bindAsEventListener(this), className: "next" });
	this.prev_month_button = header_div.build("a", { innerHTML: "&lt;", href:"#", onclick:function () { this.navMonth(this.date.getMonth() - 1 ); return false; }.bindAsEventListener(this), className: "prev" });

	if (this.options.get("month_year")=="dropdowns") {
	  this.month_select = new SelectBox(header_div, $R(0,11).map(function(m){return [Date.months[m], m]}), {className: "month", onchange: function () { this.navMonth(this.month_select.getValue()) }.bindAsEventListener(this)});
	  this.year_select = new SelectBox(header_div, [], {className: "year", onchange: function () { this.navYear(this.year_select.getValue()) }.bindAsEventListener(this)});
	  this.populateYearRange();
	} else {
	  this.month_year_label = header_div.build("span")
	}
  },
  initCalendarGrid: function() {
	var body_div = this.body_div;
	this.calendar_day_grid = [];
this.week_number_grid  =[];
	var days_table = body_div.build("table", { cellPadding: "0px", cellSpacing: "0px", width: "100%" })
	// make the weekdays!
	var weekdays_row = days_table.build("thead").build("tr");
weekdays_row.build("th",{className:"weekNumber",innerHTML: Date.weekNumberName});
	Date.weekdays.each( function(weekday) {
	  weekdays_row.build("th", {innerHTML: weekday});
	});

	var days_tbody = days_table.build("tbody")
	// Make the days!
	var row_number = 0, weekday;
	for(var cell_index = 0; cell_index<42; cell_index++)
	{
	  weekday = (cell_index+Date.dowOffset ) % 7;
	  if ( cell_index % 7==0 ) {
	days_row = days_tbody.build("tr", {className: 'row_'+row_number++});
(this.week_number_grid[cell_index] = days_row.build('th',{className:'weekNumber'})).build("div");
}
	  (this.calendar_day_grid[cell_index] = days_row.build("td", {
		  calendar_date_select: this,
		  onmouseover: function () { this.calendar_date_select.dayHover(this); },
		  onmouseout: function () { this.calendar_date_select.dayHoverOut(this) },
		  onclick: function() { this.calendar_date_select.updateSelectedDate(this, true); },
		  className: (weekday==0) || (weekday==6) ? " weekend" : "" //clear the class
		},
		{ cursor: "pointer" }
	  )).build("div");
	  this.calendar_day_grid[cell_index];
	}
  },
  initButtonsDiv: function()
  {
	var buttons_div = this.buttons_div;
	if (this.options.get("time"))
	{
	  var blank_time = $A(this.options.get("time")=="mixed" ? [[" - ", ""]] : []);
	  buttons_div.build("span", {innerHTML:"@", className: "at_sign"});

	  var t = new Date();
	  this.hour_select = new SelectBox(buttons_div,
		blank_time.concat($R(0,23).map(function(x) {t.setHours(x); return $A([t.getAMPMHour()+ " " + t.getAMPM(),x])} )),
		{
		  calendar_date_select: this,
		  onchange: function() { this.calendar_date_select.updateSelectedDate( { hour: this.value });},
		  className: "hour"
		}
	  );
	  buttons_div.build("span", {innerHTML:":", className: "seperator"});
	  var that = this;
	  this.minute_select = new SelectBox(buttons_div,
		blank_time.concat($R(0,59).select(function(x){return (x % that.options.get('minute_interval')==0)}).map(function(x){ return $A([ Date.padded2(x), x]); } ) ),
		{
		  calendar_date_select: this,
		  onchange: function() { this.calendar_date_select.updateSelectedDate( {minute: this.value }) },
		  className: "minute"
		}
	  );

	} else if (! this.options.get("buttons")) buttons_div.remove();

	if (this.options.get("buttons")) {
	  buttons_div.build("span", {innerHTML: "&#160;"});

	  if (this.options.get("time")=="mixed" || !this.options.get("time")) b = buttons_div.build("a", {
		  innerHTML: typeof T != "undefined" ? T.text('today') : "Today",
		  href: "#",
		  onclick: function() {this.today(false); return false;}.bindAsEventListener(this)
		});

	  if (this.options.get("time")=="mixed") buttons_div.build("span", {innerHTML: "&#160;|&#160;", className:"button_seperator"})

	  if (this.options.get("time")) b = buttons_div.build("a", {
		innerHTML: typeof T != "undefined" ? T.text('now') : "Now",
		href: "#",
		onclick: function() {this.today(true); return false}.bindAsEventListener(this)
	  });

	  if (!this.options.get("embedded") && !this.closeOnClick())
	  {
		buttons_div.build("span", {innerHTML: "&#160;|&#160;", className:"button_seperator"})
		buttons_div.build("a", { innerHTML: typeof T != "undefined" ? T.text('ok') : 'OK', href: "#", onclick: function() {this.close(); return false;}.bindAsEventListener(this) });
	  }
	  if (this.options.get('clear_button')) {
		buttons_div.build("span", {innerHTML: "&#160;|&#160;", className:"button_seperator"})
		buttons_div.build("a", { innerHTML: typeof T != "undefined" ? T.text('clear') : "Clear", href: "#", onclick: function() {this.clearDate(); if (!this.options.get("embedded")) this.close(); return false;}.bindAsEventListener(this) });
	  }
	}
  },
  refresh: function ()
  {
	this.refreshMonthYear();
	this.refreshCalendarGrid();

	this.setSelectedClass();
	this.updateFooter();
  },
  refreshCalendarGrid: function () {
	this.beginning_date = new Date(this.date).stripTime();
	this.beginning_date.setDate(1);
	this.beginning_date.setHours(12); // Prevent daylight savings time boundaries from showing a duplicate day
	var pre_days = this.beginning_date.getDay() // draw some days before the fact
	if (pre_days < 3) pre_days += 7;
	this.beginning_date.setDate(1 - pre_days + Date.dowOffset);

	var iterator = new Date(this.beginning_date);

	var today = new Date().stripTime();
	var this_month = this.date.getMonth();
	vdc = this.options.get("valid_date_check");
	for (var cell_index = 0;cell_index<42; cell_index++)
	{
	  day = iterator.getDate(); month = iterator.getMonth();
	  cell = this.calendar_day_grid[cell_index];
if (this.week_number_grid[cell_index]) {
	wncell = this.week_number_grid[cell_index];
	Element.remove(wncell.childNodes[0]);
	var wnd = wncell.build("div",{innerHTML:iterator.getWeek()});
}
	  Element.remove(cell.childNodes[0]); div = cell.build("div", {innerHTML:day});
	  if (month!=this_month) div.className = "other";
	  cell.day = day; cell.month = month; cell.year = iterator.getFullYear();
	  if (vdc) { if (vdc(iterator.stripTime())) cell.removeClassName("disabled"); else cell.addClassName("disabled") };
	  iterator.setDate( day + 1);
	}

	if (this.today_cell) this.today_cell.removeClassName("today");

	if ( $R( 0, 41 ).include(days_until = this.beginning_date.stripTime().daysDistance(today)) ) {
	  this.today_cell = this.calendar_day_grid[days_until];
	  this.today_cell.addClassName("today");
	}
  },
  refreshMonthYear: function() {
	var m = this.date.getMonth();
	var y = this.date.getFullYear();
	// set the month
	if (this.options.get("month_year") == "dropdowns")
	{
	  this.month_select.setValue(m, false);

	  var e = this.year_select.element;
	  if (this.flexibleYearRange() && (!(this.year_select.setValue(y, false)) || e.selectedIndex <= 1 || e.selectedIndex >= e.options.length - 2 )) this.populateYearRange();

	  this.year_select.setValue(y);

	} else {
	  this.month_year_label.update( Date.months[m] + " " + y.toString()  );
	}
  },
  populateYearRange: function() {
	this.year_select.populate(this.yearRange().toArray());
  },
  yearRange: function() {
	if (!this.flexibleYearRange())
	  return $R(this.options.get("year_range")[0], this.options.get("year_range")[1]);

	var y = this.date.getFullYear();
	return $R(y - this.options.get("year_range"), y + this.options.get("year_range"));
  },
  flexibleYearRange: function() { return (typeof(this.options.get("year_range")) == "number"); },
  validYear: function(year) { if (this.flexibleYearRange()) { return true;} else { return this.yearRange().include(year);}  },
  dayHover: function(element) {
	var hover_date = new Date(this.selected_date);
	hover_date.setYear(element.year); hover_date.setMonth(element.month); hover_date.setDate(element.day);
	this.updateFooter(hover_date.formatDate(this.options.get("format")));
  },
  dayHoverOut: function(element) { this.updateFooter(); },
  clearSelectedClass: function() {if (this.selected_cell) this.selected_cell.removeClassName("selected");},
  setSelectedClass: function() {
	if (!this.selection_made) return;
	this.clearSelectedClass()
	if ($R(0,42).include( days_until = this.beginning_date.stripTime().daysDistance(this.selected_date.stripTime()) )) {
	  this.selected_cell = this.calendar_day_grid[days_until];
	  this.selected_cell.addClassName("selected");
	}
  },
  reparse: function() { this.parseDate(); this.refresh(); },
  dateString: function() {
	return (this.selection_made) ? this.selected_date.formatDate(this.options.get("format") || '%Y-%m-%d') : "&#160;";
  },
  ISODateString: function() {
	return (this.selection_made) ? this.selected_date.formatDate('%Y-%m-%d') : this.date.formatDate('%Y-%m-%d');
  },
  parseDate: function()
  {
	var value = $(this.target_element).readAttribute('date') || $F(this.target_element).strip();
	if ("" != value) {
		var vs = value.split('-');
		for (var i = 0; i < vs.length; i++) {
			vs[i] = parseInt(vs[i], 10);
		}
		this.date = new Date(vs[0], vs[1] - 1, vs[2]);
		if (this.date.getFullYear() != vs[0] || this.date.getMonth() + 1 != vs[1] || this.date.getDate() != vs[2])
			this.date = NaN;
		else
			this.selection_made = true;
	} else {
		this.date = NaN;
	}
	if (isNaN(this.date)) {
		this.selection_made = false;
		this.date = new Date();
	}
	if (!this.validYear(this.date.getFullYear())) this.date.setYear( (this.date.getFullYear() < this.yearRange().start) ? this.yearRange().start : this.yearRange().end);
	this.selected_date = new Date(this.date);
	this.use_time = /[0-9]:[0-9]{2}/.exec(value) ? true : false;
	this.date.setDate(1);
  },
  updateFooter:function(text) { if (!text) text = this.dateString(); this.footer_div.purgeChildren(); this.footer_div.build("span", {innerHTML: text }); },
  clearDate:function() {
	if ((this.target_element.disabled || this.target_element.readOnly) && this.options.get("popup") != "force") return false;
	var last_value = this.target_element.value;
	this.target_element.value = "";
	this.clearSelectedClass();
	this.updateFooter('&#160;');
	if (last_value!=this.target_element.value) this.callback("onchange");
  },
  updateSelectedDate:function(partsOrElement, via_click) {
	var parts = $H(partsOrElement);
	if ((this.target_element.disabled || this.target_element.readOnly) && this.options.get("popup") != "force") return false;
	if (parts.get("day")) {
	  var t_selected_date = this.selected_date, vdc = this.options.get("valid_date_check");
	  for (var x = 0; x<=3; x++) t_selected_date.setDate(parts.get("day"));
	  t_selected_date.setYear(parts.get("year"));
	  t_selected_date.setMonth(parts.get("month"));

	  if (vdc && ! vdc(t_selected_date.stripTime())) { return false; }
	  this.selected_date = t_selected_date;
	  this.selection_made = true;
	}

	if (!isNaN(parts.get("hour"))) this.selected_date.setHours(parts.get("hour"));
	if (!isNaN(parts.get("minute"))) this.selected_date.setMinutes( Math.floor_to_interval(parts.get("minute"), this.options.get("minute_interval")) );
	if (parts.get("hour") === "" || parts.get("minute") === "")
	  this.setUseTime(false);
	else if (!isNaN(parts.get("hour")) || !isNaN(parts.get("minute")))
	  this.setUseTime(true);

	this.updateFooter();
	this.setSelectedClass();

	if (this.selection_made) this.updateValue();
	if (this.closeOnClick()) { this.close(); }
	if (via_click && !this.options.get("embedded")) {
	  if ((new Date() - this.last_click_at) < 333) this.close();
	  this.last_click_at = new Date();
	}
  },
  closeOnClick: function() {
	if (this.options.get("embedded")) return false;
	if (this.options.get("close_on_click")===null )
	  return (this.options.get("time")) ? false : true
	else
	  return (this.options.get("close_on_click"))
  },
  navMonth: function(month) { (target_date = new Date(this.date)).setMonth(month); return (this.navTo(target_date)); },
  navYear: function(year) { (target_date = new Date(this.date)).setYear(year); return (this.navTo(target_date)); },
  navTo: function(date) {
	if (!this.validYear(date.getFullYear())) return false;
	this.date = date;
	this.date.setDate(1);
	this.refresh();
	this.callback("after_navigate", this.date);
	return true;
  },
  setUseTime: function(turn_on) {
	this.use_time = this.options.get("time") && (this.options.get("time")=="mixed" ? turn_on : true) // force use_time to true if time==true && time!="mixed"
	if (this.use_time && this.selected_date) { // only set hour/minute if a date is already selected
	  var minute = Math.floor_to_interval(this.selected_date.getMinutes(), this.options.get("minute_interval"));
	  var hour = this.selected_date.getHours();

	  this.hour_select.setValue(hour);
	  this.minute_select.setValue(minute)
	} else if (this.options.get("time")=="mixed") {
	  this.hour_select.setValue(""); this.minute_select.setValue("");
	}
  },
  updateValue: function() {
	var last_value = this.target_element.value;
	this.target_element.value = this.dateString();
	$(this.target_element).writeAttribute('date', this.ISODateString());
	if (last_value!=this.target_element.value) this.callback("onchange");
  },
  today: function(now) {
	var d = new Date(); this.date = new Date();
	var o = $H({ day: d.getDate(), month: d.getMonth(), year: d.getFullYear(), hour: d.getHours(), minute: d.getMinutes()});
	if ( ! now ) o = o.merge({hour: "", minute:""});
	this.updateSelectedDate(o, true);
	this.refresh();
  },
  close: function() {
	if (this.closed) return false;
	this.callback("before_close");
	this.target_element.calendar_date_select = null;
	Event.stopObserving(document, "mousedown", this.closeIfClickedOut_handler);
	Event.stopObserving(document, "keypress", this.keyPress_handler);
	this.calendar_div.remove(); this.closed = true;
	if (this.iframe) this.iframe.remove();
	if (this.target_element.type != "hidden" && ! this.target_element.disabled) this.target_element.focus();
	this.callback("after_close");
  },
  closeIfClickedOut: function(e) {
	if (! $(Event.element(e)).descendantOf(this.calendar_div) ) this.close();
  },
  keyPress: function(e) {
	if (e.keyCode==Event.KEY_ESC) this.close();
  },
  callback: function(name, param) { if (this.options.get(name)) { this.options.get(name).bind(this.target_element)(param); } }
}

Autocompleter.LocalAdvanced = Class.create(Autocompleter.Base, {
	initialize: function(element, update, array, options) {
		this.ready = false;
		this.baseInitialize(element, update, options);
		this.options.array = array;
		this.wrapper = $(this.element.parentNode);

		if (!this.element.hacks) {
			this.element.should_use_borderless_hack = Prototype.Browser.WebKit;
			this.element.should_use_shadow_hack = Prototype.Browser.IE || Prototype.Browser.Opera;
			this.element.hacks = true;
		}
		if (this.element.should_use_borderless_hack  || this.element.should_use_shadow_hack) { this.wrapper.addClassName('tokenizer_input_borderless'); }

		this.options.onShow = function(element,update) {
			Position.clone(element.parentNode.parentNode, update, {
				setHeight: false,
				setWidth: false,
				offsetTop: element.parentNode.parentNode.offsetHeight
			});
			update.show();
		}
		this.options.onHide = function(element, update){ update.hide() };
		if ('' != this.element.value) {
			var tags = this.element.value.split(',');
			for (var i = 0, l = tags.length; i < l; i++) {
				this.updateElement(tags[i]);
			}
			this.element.value = '';
		}
		this.ready = true;
	},
	getUpdatedChoices: function() {
		this.updateChoices(this.options.selector(this));
	},
	onBlur: function($super, event) {
		$super();
		//move itself back to the end on blur
		if (this.wrapper.nextSiblings().length > 0) {
			this.wrapper.nextSiblings().last().insert({
				after: this.wrapper
			});
		}
	},
	set_input_size: function(size) {
		size = size || 20;
		this.element.setStyle({width: size + "px"});
	},
	onKeyPress: function(event) {
		//dynamically resize the input field
		var new_size = 20 + (this.element.value.length * 7);
		if (new_size <= 340) {
			this.set_input_size(new_size);
		} else {
			this.set_input_size(340);
		}
		//active is when there's suggesitons found
		if (this.active) {
			switch (event.keyCode) {
				case Event.KEY_TAB:
				case Event.KEY_RETURN:
					this.selectEntry();
					Event.stop(event);
				case Event.KEY_ESC:
					this.hide();
					this.active = false;
					Event.stop(event);
					return;
				case Event.KEY_LEFT:
				case Event.KEY_RIGHT:
					return;
				case Event.KEY_UP:
					this.markPrevious();
					this.render();
					Event.stop(event);
					return;
				case Event.KEY_DOWN:
					this.markNext();
					this.render();
					Event.stop(event);
					return;
			}
		} else {
			if (event.keyCode == Event.KEY_TAB || event.keyCode == Event.KEY_RETURN || (Prototype.Browser.WebKit > 0 && event.keyCode == 0) || event.keyCode == 44 /* , comma */ ||  event.keyCode == 188 ) {
				var tag = this.element.value.strip().sub(',', '');
				if ('' != tag) {
					this.updateElement(tag);
					Event.stop(event);
				} else if (event.keyCode != KEY_TAB) {
					Event.stop(event);
				}
				this.element.value = "";
				this.set_input_size();
				return false;
			}
			switch (event.keyCode) {
				//jump left to token
				case Event.KEY_LEFT:
				case Event.KEY_BACKSPACE:
					if (this.element.value == "" && typeof this.wrapper.previous().token != "undefined") {
						this.wrapper.previous().token.select();
					}
					return;
				//jump right to token
				case Event.KEY_RIGHT:
					if (this.element.value == "" && this.wrapper.next() && typeof this.wrapper.next().token != "undefined") {
						this.wrapper.next().token.select();
					}
			}
		}

		this.changed = true;
		this.hasFocus = true;

		if (this.observer) clearTimeout(this.observer);
		this.observer =
		setTimeout(this.onObserverEvent.bind(this), this.options.frequency * 1000);
	},
	updateElement: function(selectedElement) {
		if (this.options.updateElement) {
			this.options.updateElement(selectedElement, this);
			return;
		}
		var value = '';
		if (this.options.select) {
			var nodes = $(selectedElement).select('.' + this.options.select) || [];
			if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
		} else
			value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
		var bounds = this.getTokenBounds();
		if (bounds[0] != -1) {
			var newValue = this.element.value.substr(0, bounds[0]);
			var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
			if (whitespace)
				newValue += whitespace[0];
			this.element.value = newValue + value + this.element.value.substr(bounds[1]);
		} else {
			this.element.value = value;
		}
		this.oldElementValue = this.element.value;
		this.element.focus();
		if (this.options.afterUpdateElement)
			this.options.afterUpdateElement(this.element, selectedElement);
	},
	setOptions: function(options) {
		this.options = Object.extend({
			choices: 10,
			partialSearch: true,
			partialChars: 2,
			ignoreCase: true,
			fullSearch: false,
			selector: function(instance) {
				var ret = [];
				// Beginning matches
				var partial = [];
				// Inside matches
				var entry = instance.getToken();
				var count = 0;

				for (var i = 0; i < instance.options.array.length && ret.length < instance.options.choices; i++) {
					var elem = instance.options.array[i];
					var elem_name = elem[instance.options.search_field];
					var foundPos = instance.options.ignoreCase ?
					elem_name.toLowerCase().indexOf(entry.toLowerCase()) :
					elem_name.indexOf(entry);

					while (foundPos != -1) {
						if (foundPos == 0 && elem_name.length != entry.length) {
							var value = "<strong>" + elem_name.substr(0, entry.length) + "</strong>" + elem_name.substr(entry.length);
							ret.push(
								"<li value='" + i + "'>" + "<div>" + value + "</div></li>"
								);
							break;
						} else if (entry.length >= instance.options.partialChars && instance.options.partialSearch && foundPos != -1) {
							if (instance.options.fullSearch || /\s/.test(elem_name.substr(foundPos - 1, 1))) {
								var value = elem_name.substr(0, foundPos) + "<strong>" + elem_name.substr(foundPos, entry.length) + "</strong>" + elem_name.substr(foundPos + entry.length)

								partial.push(
									"<li value='" + i + "'>" + "<div>" + value + "</div>" + "<div>" + elem.email + "</div>" + "</li>"
								);
								break;
							}
						}
						foundPos = instance.options.ignoreCase ?
						elem_name.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
						elem_name.indexOf(entry, foundPos + 1);
					}
				}
				if (partial.length)
					ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
				return "<ul>" + ret.join('') + "</ul>";
			}
		},
		options || {});
	}
});
HiddenInput = Class.create({
	initialize: function(element, auto_complete) {
		this.element = $(element);
		this.auto_complete = auto_complete;
		this.token;
		Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));

	},
	onKeyPress: function(event) {
		if (this.token.selected) {
			switch (event.keyCode) {
				case Event.KEY_LEFT:
				this.token.element.insert({
					before:
					this.auto_complete.wrapper
				})
				this.token.deselect();
				this.auto_complete.element.focus();
				return false;
				case Event.KEY_RIGHT:
				this.token.element.insert({
					after:
					this.auto_complete.wrapper
				})
				this.token.deselect();
				this.auto_complete.element.focus();
				return false;
				case Event.KEY_BACKSPACE:
				case Event.KEY_DELETE:
				this.token.element.remove();
				this.auto_complete.element.focus();
				return false;
			}
		}
	}
});
Token = Class.create({
	initialize: function(element, hidden_input) {
		this.element = $(element);
		this.hidden_input = hidden_input;
		this.element.token = this;
		this.selected = false;
		Event.observe(document, 'click', this.onclick.bindAsEventListener(this));
	},
	select: function() {
		this.hidden_input.token = this;
		this.hidden_input.element.activate();
		this.selected = true;
		this.element.addClassName('token_selected');
	},
	deselect: function() {
		this.hidden_input.token = undefined;
		this.selected = false;
		this.element.removeClassName('token_selected')
	},
	onclick: function(event) {
		if (this.detect(event) && !this.selected) {
			this.select();
		} else {
			this.deselect();
		}
	},
	detect: function(e) {
		//find the event object
		var eventTarget = e.target ? e.target: e.srcElement;
		var token = eventTarget.token;
		var candidate = eventTarget;
		while (token == null && candidate.parentNode) {
			candidate = candidate.parentNode;
			token = candidate.token;
		}
		return token != null && token.element == this.element;
	}
});

var Hit = Class.create({
	saveForElement: function(type, element) {
		var selected = undefined;
		if (element.tagName == 'SELECT') {
			selected = element.options[element.selectedIndex].value;
		} else {
			selected = element.value;
		}
		var id, search;
		var holder = $(element).up('.hit-block');
		if (! holder) return;
		id = holder.readAttribute('hit');
		search = holder.readAttribute('search');
		if (! isNaN(id) && 0 < id) {
			this.notifyOfSave({
				property: type,
				hit: id,
				value: selected,
				search: search
				},
				element);
		}
	},
	notifyOfSave: function(options, element) {
		new Ajax.Request(
			'/hit-options.cgi', {
				method: 'post',
				parameters: options,
				onSuccess: function(transport) {
					new Hit().reportSuccess(element);
				},
				onFailure: function(transport) {
					if (transport.status == 1223) {
						new Hit().reportSuccess(element);
					} else {
						new Hit().reportFailure(element);
					}
				}
			});
	},
	reportSuccess: function(element) {

	},
	reportFailure: function(element) {
		alert("Failed");
	}
});

var AnalyzeClass = Class.create({
	setGraphType: function(graph) {
		var holder = $(graph).up('.analyzepro-report-block');
		if (! holder) return false;
		var imageHolder = holder.down('.report-block-image');
		if (! imageHolder) return false;
		var img = imageHolder.getElementsByTagName('IMG')[0];

		var chosen;
		if (graph.nodeName == 'SELECT') {
			chosen = graph.options[graph.selectedIndex].value;
		} else {
			chosen = graph.value;
		}

		var images = imageHolder.getElementsByTagName('A');
		for (var i = 0, l = images.length; i < l; i++) {
			var node = $(images[i]);
			if (node.readAttribute('type') == chosen) {
				img.src = node.readAttribute('href');
				break;
			}
		}
		return true;
	},
	setGraphDisabled: function(graph) {
		var holder = $(graph).up('.analyzepro-report-block');
		if (! holder) return false;
		if (graph.checked) {
			holder.addClassName('analyzepro-disabled');
		} else {
			holder.removeClassName('analyzepro-disabled');
		}
		var select = holder.getElementsByTagName('SELECT');
		for (var i = 0, l = select.length; i < l; i++) {
			select[i].disabled = graph.checked;
		}
		var inputs = holder.getElementsByTagName('INPUT');
		for (var i = 0, l = inputs.length; i < l; i++) {
			if (! $(inputs[i]).hasClassName('remove')) {
				inputs[i].disabled = graph.checked;
			}
		}
		var buttons = holder.getElementsByTagName('BUTTON');
		for (var i = 0, l = buttons.length; i < l; i++) {
			buttons[i].disabled = graph.checked;
		}
		var link = holder.getElementsByTagName('A');
		for (var i = 0, l = link.length; i < l; i++) {
			var li = $(link[i]);
			if (graph.checked) {
				li.writeAttribute('original', li.readAttribute('href'));
				li.writeAttribute('href', 'javascript:void(0)');
			} else {
				li.writeAttribute('href', li.readAttribute('original'));
			}
		}
		return true;
	},
	durationChange: function(element) {
		var holder = $(element).up('.dates');
		var duration = element.options[element.selectedIndex].value;
		var inputs = holder.getElementsByTagName('INPUT');
		if ('' == duration) {
			for (var i = 1, l = inputs.length; i < l; i++) {
				inputs[i].disabled = false;
				inputs[i].removeClassName('disabled');
			}
		} else {
			for (var i = 1, l = inputs.length; i < l; i++) {
				inputs[i].disabled = true;
				inputs[i].addClassName('disabled');
			}
		}
	},
	setEditorText: function(element) {
		var link = $(element);
		var box = link.up();
		var textbox = box.previousSiblings()[0];
		var children = textbox.childElements();
		var text = "";

		if (link.innerHTML == textbox.readAttribute('save')) {
			for (var i = 0, l = children.length; i < l; i++) {
				if (children[i].tagName == 'TEXTAREA') {
					text += children[i].value;
				}
			}
			var paragraphs = -1 == text.indexOf("\r\n") ? text.split("\n\n") : text.split("\r\n\r\n");
			textbox.removeChild(children[0]);
			for (var i = 0, l = paragraphs.length; i < l; i++) {
				textbox.appendChild(Builder.node('p', paragraphs[i]));
			}
			link.innerHTML = textbox.readAttribute('edit');
			var upH = textbox.up('div', 2);
			var inI = upH.up('.analyzepro-report-block').getElementsByTagName('INPUT');
			var myName = "";
			for (var i = 0, l = inI.length; i < l; i++) {
				if (inI[i].type == 'hidden' && inI[i].name == 'content') {
					myName = inI[i].value;
				}
			}
			var ta = upH.getElementsByTagName('TEXTAREA');
			if (ta.length > 0) {
				ta[0].innerHTML = text;
			} else {
				upH.appendChild(Builder.node('textarea', { rows: 1, cols: 1, name: 'text-' + myName, 'class': 'hidden' }, text));
			}
		} else {
			for (var i = 0, l = children.length; i < l; i++) {
				text += children[i].textContent + "\r\n\r\n";
			}
			for (var i = children.length - 1; i >= 0; i--) {
				textbox.removeChild(children[i]);
			}
			var editorType = textbox.readAttribute('type');
			if (editorType == 'textarea') {
				var edit = Builder.node('textarea', { rows: 5, cols: 40, name: 'editor-', 'class': 'span-9' }, text);
				textbox.appendChild(edit);
			}
			link.innerHTML = textbox.readAttribute('save');
		}
		return false;
	},
	move: function(node, direction) {
		node = $(node);
		var block = node.up('.analyzepro-report-block');
		var h = block.up();
		if (direction == 'up') {
			var n = block.previous('.analyzepro-report-block');
			if (n)
				h.insertBefore(block.remove(), n);
		} else {
			var n = block.next('.analyzepro-report-block');
			if (n) {
				n = n.next('.analyzepro-report-block');
				h.insertBefore(block.remove(), n);
			}
		}
		return false;
	},
	setName: function(from) {
		var name = $(from).value;
		var h1 = $$('h1');
		if (h1.length > 0) {
			h1.each(function(m) { m.innerHTML = ''; m.appendChild(document.createTextNode(name)); });
		}
	},
	waitForGraphs: function() {
		setTimeout('Analyze.checkGraphStatus();', 2000);
	},
	checkGraphStatus: function() {
		var info = $('report-info');
		if (! info) return;
		var report = info.readAttribute('report');
		var checker = new Ajax.Request(
			'/analyzepro.cgi', {
				method: 'post',
				parameters: { id: report, op: 'checkgraphstatus' },
				onComplete: function(transport) {
					if (transport.status == 204 || transport.status == 1223) {
						this.waitForGraphs();
					} else if (transport.status == 200) {
						try {
							var list = transport.responseXML;
							var pendingTypes = false;
							if (list && list.documentElement) {
								var blocks = list.documentElement.getElementsByTagName('block');
								for (var i = 0, l = blocks.length; i < l; i++) {
									var blockPending = false;
									var types = blocks[i].getElementsByTagName('type');
									var typeUrls = [];
									var results = [];
									for (var ii = 0, ll = types.length; ii < ll; ii++) {
										if (types[ii].hasChildNodes()) {
											if (types[ii].firstChild.nodeName == 'pending') {
												pendingTypes = true;
												blockPending = true;
											} else if (types[ii].firstChild.nodeName == 'uri') {
												var url = types[ii].firstChild.textContent;
												typeUrls.push([types[ii].getAttribute('name'),  url]);
												if (url.indexOf('analyzepro-loading') != -1) {
													blockPending = true;
													pendingTypes = true;
												}
											}
										}
									}
									var node = $('reportblock-type-' + blocks[i].getAttribute('name'));
									if (node) {
										if (! blockPending) {
											node.removeClassName('pending');
										}
										var images = node.select('.report-block-image');
										if (typeUrls.length > 0) {
											if (images.length) {
											  	var select = node.select('select');
												var selected = 0;
												if (select.length) {
													selected = select[0].selectedIndex;
												}
												var links = images[0].select('a');
												var lmax = links.length;
												var tmax = typeUrls.length;
												var max = lmax < tmax ? lmax : tmax;
												if (max > 0) {
													for (var t = 0; t < max; t++) {
														links[t].writeAttribute('type', typeUrls[t][0]);
														links[t].writeAttribute('href', typeUrls[t][1]);
													}
													images[0].select('img')[0].src = typeUrls[selected][1];
												}
											}
										} else {
											var resultDefs = blocks[i].getElementsByTagName('result');
											var ul = document.createElement('UL');
											images[0].update('');
											for (var ii = 0, ll = resultDefs.length; ii < ll; ii++) {
												var li = document.createElement('LI');
												var lable = resultDefs[ii].getAttribute('label');
												if (lable == '...') {
													li.appendChild(document.createTextNode(lable));
												} else {
													li.appendChild(document.createTextNode(resultDefs[ii].getAttribute('label') + ' (' + resultDefs[ii].textContent + ')'));
												}
												ul.appendChild(li);
											}
											images[0].appendChild(ul);
										}
									}
								}
							} else {
								pendingTypes = true;
							}
							if (pendingTypes) {
								this.waitForGraphs();
							}
						} catch (err) {
							this.waitForGraphs();
						}
					} else {
						this.waitForGraphs();
					}
				}
			});
	},
	setSubmitLabel: function(input) {
		var submit = $('analyze-submit');
		if (! submit) return;
		input = $(input);
		if (input.readAttribute('name') == 'delete') {
			var label = input.checked ? submit.readAttribute('deletelabel') : submit.readAttribute('savelabel');
			if ('' != label) {
				submit.update(label);
			}
		}
	}
});
var TagClass = Class.create({
	updateElement: function(item, ref) {
		ref.element.value = '';
		var tag = item.tagName ? item.lastChild.innerHTML.stripTags() : item;
		tag = tag.toLowerCase();
		var token = Builder.node('a', {
				"class": 'token',
				href: "#",
				tabindex: "-1"
			},
			Builder.node('span', Builder.node('span', Builder.node('span', Builder.node('span', {}, [
				Builder.node('input', { type: "hidden", name: "tags-" + ref.options.what,
					value: tag
					}),
				tag,
				Builder.node('span', {
						"class":'x',
						onmouseout:"this.className='x'",
						onmouseover:"this.className='x_hover'",
						onclick:"return Tag.removeTag(this);"
					},
					" "
					)
				]))))
			);
		$(token).down(4).next().innerHTML = "&nbsp;";
		var hidden_input = new HiddenInput('hidden-autocomplete-' + ref.options.what, this);
		new Token(token, hidden_input);
		$('autocomplete-display-' + ref.options.what).insert({before:token});
		if (ref.ready) {
			var t = new Ajax.Request(
				'/tags.cgi', {
					method: 'post',
					parameters: { hit: ref.options.what, tag: tag, operation: 'add' }
				});
		}
	},
	removeTag: function(target) {
		if (target) {
			var input = target.previous('input');
			if (input && '' != input.value) {
				var hit = parseInt(input.name.replace(/tags-/, ''));
				if (! isNaN(hit)) {
					new Ajax.Request(
						'/tags.cgi', {
							method: 'post',
							parameters: { hit: hit, tag: input.value, operation: 'remove' }
						});
				}
			}
			target.parentNode.parentNode.parentNode.parentNode.parentNode.remove(true);
		}

		return false;
	}
});
var WNMClass = Class.create({
	monitors: null,
	getMonitors: function() {
		if (this.monitors == null) {
			this.monitors = $$('input[name=monitor]');
		}
		return this.monitors;
	},
	checkMonitorsSelected: function(e) {
		var checked = 0;
		var monitors = this.getMonitors();
		for (var i = 0, l = monitors.length; i < l; i++) {
			if (monitors[i].checked) {
				checked++;
			}
		}

		var all = $('all-monitors')
		if (all) {
			if (checked == this.monitorCount) {
				all.checked = true;
			} else {
				all.checked = false;
			}
			this.setMonitorToggleLabel(all);
		}
		return true;
	},
	toggleMonitors: function(e) {
		var all = e ? Event.element(e) : $('all-monitors');
		if (! all) return false;
		var monitors = this.getMonitors();
		for (var i = 0, l = monitors.length; i < l; i++) {
			monitors[i].checked = all.checked;
		}
		this.setMonitorToggleLabel(all);
		if (e) Event.stop(e);
	},
	setMonitorToggleLabel: function(all) {
		var label = all.up('label');
		if (label) {
			var span = label.down('span');
			if (span) {
				var text = label.readAttribute(all.checked ? 'toggle-off' : 'toggle-on');
				span.innerHTML = text;
			}
		}
	},
	spinSubmit: function(element) {
		if (null == element) return false;
		if (element.disabled) return false;
		element = $(element);
		element.down('img').src = "/pics/loading.gif";
		element.writeAttribute('disbled', 'disabled');
		element.up('form').submit();
	}
});
var ResultClass = Class.create({
	addToCollection: function(button) {
		var form = $(button).up('form');
		var selhit = form.select('input[name="selhit"]');
		var selhits = selhit.length;
		if (0 == selhits) {
			return false;
		}
		var add = [];
		for (var i = 0; i < selhits; i++) {
			if (selhit[i].checked) {
				add.push(selhit[i].value);
				selhit[i].checked = false;
				if(selhit[i].value) {
					var selhit_array = selhit[i].value.split(";");
					var selhit_id = selhit_array[0];
					var language = $(document.documentElement).readAttribute('lang') || 'en';
					if(selhit_id) {
						switch (language) {
							case 'en': added_msg = 'Added to Collection!'; break;
							case 'fi': added_msg = 'Lisätty koontiin!'; break;
							default: added_msg = 'Added to Collection!';
						}
						var added_msg_area = document.getElementById( 'added_to_collection_' + selhit_id);
						if( added_msg_area ) {
							added_msg_area.innerHTML = added_msg;
						}
					}
				}
			}
		}
		if (add.length > 0) {
			var targetChooser = $('collection-destination');
			var target = targetChooser.options[targetChooser.selectedIndex].value;
			$(button).writeAttribute('disabled', 'disabled');
			targetChooser.writeAttribute('disabled', 'disabled');
			new Ajax.Request(
				'/selhit.cgi',
				{
					method: 'post',
					parameters: {
						selhit: add,
						collection: target,
						collect: 1
						},
					onComplete: function(transport) {
							$(button).removeAttribute('disabled');
							targetChooser.removeAttribute('disabled');
						}
				}
				);
		}
	}
});
var Analyze = new AnalyzeClass();
var Tag = new TagClass();
var WNM = new WNMClass();
var Result = new ResultClass();

Event.observe(window, 'dom:loaded', function() {
	var tokenizers = $$('.tokenizer');
	var tl = tokenizers.length;
	if (0 < tl) {
		for (var i = 0; i < tl; i++) {
			var it = tokenizers[i];
			var block = it.up('.hit-block');
			var hit = block.readAttribute('hit');
			new Autocompleter.LocalAdvanced('autocomplete-' + hit, 'autocomplete-populate-' + hit, allTags, {
				frequency:0.1,
				what:hit,
				updateElement:Tag.updateElement,
				search_field:'name'
				});
		}
	}
	if (typeof CalendarDateSelect != "undefined") {
		$$('input.calendar').each(function(o) {
			$(o).observe('click', function() {
				new CalendarDateSelect($(o), {month_year:'label', year_range:10, format:'%d.%m.%Y'});
				});
			});
	}
	var all = $('all-monitors');
	if (all) {
		all.observe('click', function() { WNM.toggleMonitors(); });
		$$('input[name=monitor]').each(function(input) {input.observe('click', function() { WNM.checkMonitorsSelected(); }); });
		WNM.checkMonitorsSelected();
	}
	var search = $('search');
	if (search) {
		var i = new Image();
		i.src = "/pics/loading.gif";
	}
	var pending = $$('.pending');
	if (pending.length > 0) {
		Analyze.waitForGraphs();
	}
});

