/*
This software is allowed to use under GPL or you need to obtain Commercial or Enterise License
to use it in non-GPL project. Please contact sales@dhtmlx.com for details
*/
scheduler.templates.calendar_month = scheduler.date.date_to_str("%F %Y");
scheduler.templates.calendar_scale_date = scheduler.date.date_to_str("%D");
scheduler.templates.calendar_date = scheduler.date.date_to_str("%d");
scheduler.config.minicalendar = {
	mark_events: true
};
scheduler._synced_minicalendars = [];
scheduler.renderCalendar = function(obj, _prev, is_refresh) {
	var cal = null;
	var date = obj.date || (new Date());
	if (typeof date == "string")
		date = this.templates.api_date(date);

	if (!_prev) {
		var cont = obj.container;
		var pos = obj.position;

		if (typeof cont == "string")
			cont = document.getElementById(cont);

		if (typeof pos == "string")
			pos = document.getElementById(pos);
		if (pos && (typeof pos.left == "undefined")) {
			var tpos = getOffset(pos);
			pos = {
				top: tpos.top + pos.offsetHeight,
				left: tpos.left
			};
		}
		if (!cont)
			cont = scheduler._get_def_cont(pos);

		cal = this._render_calendar(cont, date, obj);
		cal.onclick = function(e) {
			e = e || event;
			var src = e.target || e.srcElement;

			if (src.className.indexOf("dhx_month_head") != -1) {
				var pname = src.parentNode.className;
				if (pname.indexOf("dhx_after") == -1 && pname.indexOf("dhx_before") == -1) {
					var newdate = scheduler.templates.xml_date(this.getAttribute("date"));
					newdate.setDate(parseInt(src.innerHTML, 10));
					scheduler.unmarkCalendar(this);
					scheduler.markCalendar(this, newdate, "dhx_calendar_click");
					this._last_date = newdate;
					if (this.conf.handler) this.conf.handler.call(scheduler, newdate, this);
				}
			}
		};
	} else {
		cal = this._render_calendar(_prev.parentNode, date, obj, _prev);
		scheduler.unmarkCalendar(cal);
	}

	if (scheduler.config.minicalendar.mark_events) {
		var start = scheduler.date.month_start(date);
		var end = scheduler.date.add(start, 1, "month");
		var evs = this.getEvents(start, end);
		var filter = this["filter_" + this._mode];
		for (var i = 0; i < evs.length; i++) {
			var ev = evs[i];
			if (filter && !filter(ev.id, ev))
				continue;
			var d = ev.start_date;
			if (d.valueOf() < start.valueOf())
				d = start;
			d = scheduler.date.date_part(new Date(d.valueOf()));
			while (d < ev.end_date) {
				this.markCalendar(cal, d, "dhx_year_event");
				d = this.date.add(d, 1, "day");
				if (d.valueOf() >= end.valueOf())
					break;
			}
		}
	}

	this._markCalendarCurrentDate(cal);

	cal.conf = obj;
	if (obj.sync && !is_refresh)
		this._synced_minicalendars.push(cal);

	return cal;
};
scheduler._get_def_cont = function(pos) {
	if (!this._def_count) {
		this._def_count = document.createElement("DIV");
		this._def_count.className = "dhx_minical_popup";
		this._def_count.onclick = function(e) { (e || event).cancelBubble = true; };
		document.body.appendChild(this._def_count);
	}

	this._def_count.style.left = pos.left + "px";
	this._def_count.style.top = pos.top + "px";
	this._def_count._created = new Date();

	return this._def_count;
};
scheduler._locateCalendar = function(cal, date) {
	var table = cal.childNodes[2].childNodes[0];
	if (typeof date == "string")
		date = scheduler.templates.api_date(date);

	var d = cal.week_start + date.getDate() - 1;
	return table.rows[Math.floor(d / 7)].cells[d % 7].firstChild;
};
scheduler.markCalendar = function(cal, date, css) {
	this._locateCalendar(cal, date).className += " " + css;
};
scheduler.unmarkCalendar = function(cal, date, css) {
	date = date || cal._last_date;
	css = css || "dhx_calendar_click";
	if (!date) return;
	var el = this._locateCalendar(cal, date);
	el.className = (el.className || "").replace(RegExp(css, "g"));
};
scheduler._week_template = function(width) {
	var summ = (width || 250);
	var left = 0;

	var week_template = document.createElement("div");
	var dummy_date = this.date.week_start(new Date());
	for (var i = 0; i < 7; i++) {
		this._cols[i] = Math.floor(summ / (7 - i));
		this._render_x_header(i, left, dummy_date, week_template);
		dummy_date = this.date.add(dummy_date, 1, "day");
		summ -= this._cols[i];
		left += this._cols[i];
	}
	week_template.lastChild.className += " dhx_scale_bar_last";
	return week_template;
};
scheduler.updateCalendar = function(obj, sd) {
	obj.conf.date = sd;
	this.renderCalendar(obj.conf, obj, true);
};
scheduler._mini_cal_arrows = ["&nbsp", "&nbsp"];
scheduler._render_calendar = function(obj, sd, conf, previous) {
	/*store*/
	var ts = scheduler.templates;
	var temp = this._cols;
	this._cols = [];
	var temp2 = this._mode;
	this._mode = "calendar";
	var temp3 = this._colsS;
	this._colsS = {height: 0};
	var temp4 = new Date(this._min_date);
	var temp5 = new Date(this._max_date);
	var temp6 = new Date(scheduler._date);
	var temp7 = ts.month_day;
	ts.month_day = ts.calendar_date;

	sd = this.date.month_start(sd);
	var week_template = this._week_template(obj.offsetWidth - 1);

	var d;
	if (previous)
		d = previous; else {
		d = document.createElement("DIV");
		d.className = "dhx_cal_container dhx_mini_calendar";
	}
	d.setAttribute("date", this.templates.xml_format(sd));
	d.innerHTML = "<div class='dhx_year_month'></div><div class='dhx_year_week'>" + week_template.innerHTML + "</div><div class='dhx_year_body'></div>";

	d.childNodes[0].innerHTML = this.templates.calendar_month(sd);
	if (conf.navigation) {
		var move_minicalendar_date = function(calendar, diff) {
			var date = scheduler.date.add(calendar._date, diff, "month");
			scheduler.updateCalendar(calendar, date);
			if (scheduler._date.getMonth() == calendar._date.getMonth() && scheduler._date.getFullYear() == calendar._date.getFullYear()) {
				scheduler._markCalendarCurrentDate(calendar);
			}
		};

		var css_classnames = ["dhx_cal_prev_button", "dhx_cal_next_button"];
		var css_texts = ["left:1px;top:2px;position:absolute;", "left:auto; right:1px;top:2px;position:absolute;"];
		var diffs = [-1, 1];
		var handler = function(diff) {
			return function() {
				if (conf.sync) {
					var calendars = scheduler._synced_minicalendars;
					for (var k = 0; k < calendars.length; k++) {
						move_minicalendar_date(calendars[k], diff);
					}
				} else {
					move_minicalendar_date(d, diff);
				}
			}
		};
		for (var j = 0; j < 2; j++) {
			var arrow = document.createElement("DIV");
			//var diff = diffs[j];
			arrow.className = css_classnames[j];
			arrow.style.cssText = css_texts[j];
			arrow.innerHTML = this._mini_cal_arrows[j];
			d.firstChild.appendChild(arrow);
			arrow.onclick = handler(diffs[j])
		}
	}
	d._date = new Date(sd);

	d.week_start = (sd.getDay() - (this.config.start_on_monday ? 1 : 0) + 7) % 7;

	var dd = this.date.week_start(sd);
	this._reset_month_scale(d.childNodes[2], sd, dd);

	var r = d.childNodes[2].firstChild.rows;
	for (var k = r.length; k < 6; k++) {
		var last_row = r[r.length - 1];
		r[0].parentNode.appendChild(last_row.cloneNode(true));
		var last_day_number = parseInt(last_row.childNodes[last_row.childNodes.length - 1].childNodes[0].innerHTML);
		last_day_number = (last_day_number < 10) ? last_day_number : 0; // previous week could end on 28-31, so we should start with 0
		for (var ri = 0; ri < r[k].childNodes.length; ri++) {
			r[k].childNodes[ri].className = "dhx_after";
			r[k].childNodes[ri].childNodes[0].innerHTML = scheduler.date.to_fixed(++last_day_number);
		}
	}

	if (!previous)
		obj.appendChild(d);

	d.childNodes[1].style.height = (d.childNodes[1].childNodes[0].offsetHeight - 1) + "px"; // dhx_year_week should have height property so that day dates would get correct position. dhx_year_week height = height of it's child (with the day name)

	/*restore*/
	this._cols = temp;
	this._mode = temp2;
	this._colsS = temp3;
	this._min_date = temp4;
	this._max_date = temp5;
	scheduler._date = temp6;
	ts.month_day = temp7;
	return d;
};
scheduler.destroyCalendar = function(cal, force) {
	if (!cal && this._def_count && this._def_count.firstChild) {
		if (force || (new Date()).valueOf() - this._def_count._created.valueOf() > 500)
			cal = this._def_count.firstChild;
	}
	if (!cal) return;
	cal.onclick = null;
	cal.innerHTML = "";
	if (cal.parentNode)
		cal.parentNode.removeChild(cal);
	if (this._def_count)
		this._def_count.style.top = "-1000px";
};
scheduler.isCalendarVisible = function() {
	if (this._def_count && parseInt(this._def_count.style.top, 10) > 0)
		return this._def_count;
	return false;
};
scheduler.attachEvent("onTemplatesReady", function() {
	dhtmlxEvent(document.body, "click", function() { scheduler.destroyCalendar(); });
});

scheduler.templates.calendar_time = scheduler.date.date_to_str("%d-%m-%Y");

scheduler.form_blocks.calendar_time = {
	render: function() {
		var html = "<input class='dhx_readonly' type='text' readonly='true'>";

		var cfg = scheduler.config;
		var dt = this.date.date_part(new Date());

		var last = 24 * 60, first = 0;
		if (cfg.limit_time_select) {
			first = 60 * cfg.first_hour;
			last = 60 * cfg.last_hour + 1;  // to include "17:00" option if time select is limited
		}
		dt.setHours(first / 60);

		html += " <select>";
		for (var i = first; i < last; i += this.config.time_step * 1) { // `<` to exclude last "00:00" option
			var time = this.templates.time_picker(dt);
			html += "<option value='" + i + "'>" + time + "</option>";
			dt = this.date.add(dt, this.config.time_step, "minute");
		}
		html += "</select>";

		var full_day = scheduler.config.full_day;

		return "<div style='height:30px;padding-top:0; font-size:inherit;' class='dhx_section_time'>" + html + "<span style='font-weight:normal; font-size:10pt;'> &nbsp;&ndash;&nbsp; </span>" + html + "</div>";
	},
	set_value: function(node, value, ev) {

		var inputs = node.getElementsByTagName("input");
		var selects = node.getElementsByTagName("select");

		var _init_once = function(inp, date, number) {
			inp.onclick = function() {
				scheduler.destroyCalendar(null, true);
				scheduler.renderCalendar({
					position: inp,
					date: new Date(this._date),
					navigation: true,
					handler: function(new_date) {
						inp.value = scheduler.templates.calendar_time(new_date);
						inp._date = new Date(new_date);
						scheduler.destroyCalendar();
						if (scheduler.config.event_duration && scheduler.config.auto_end_date && number == 0) { //first element = start date
							_update_minical_select();
						}
					}
				});
			};
		};

		if (scheduler.config.full_day) {
			if (!node._full_day) {
				var html = "<label class='dhx_fullday'><input type='checkbox' name='full_day' value='true'> " + scheduler.locale.labels.full_day + "&nbsp;</label></input>";
				if (!scheduler.config.wide_form)
					html = node.previousSibling.innerHTML + html;
				node.previousSibling.innerHTML = html;
				node._full_day = true;
			}
			var input = node.previousSibling.getElementsByTagName("input")[0];

			var isFulldayEvent = (scheduler.date.time_part(ev.start_date) == 0 && scheduler.date.time_part(ev.end_date) == 0);
			input.checked = isFulldayEvent;

			selects[0].disabled = input.checked;
			selects[1].disabled = input.checked;

			input.onclick = function() {
				if (input.checked == true) {
					var obj = {};
					scheduler.form_blocks.calendar_time.get_value(node, obj);

					var start_date = scheduler.date.date_part(obj.start_date);
					var end_date = scheduler.date.date_part(obj.end_date);

					if (+end_date == +start_date || (+end_date >= +start_date && (ev.end_date.getHours() != 0 || ev.end_date.getMinutes() != 0)))
						end_date = scheduler.date.add(end_date, 1, "day");
				}

				var start = start_date || ev.start_date;
				var end = end_date || ev.end_date;
				_attach_action(inputs[0], start);
				_attach_action(inputs[1], end);
				selects[0].value = start.getHours() * 60 + start.getMinutes();
				selects[1].value = end.getHours() * 60 + end.getMinutes();

				selects[0].disabled = input.checked;
				selects[1].disabled = input.checked;

			};
		}

		if (scheduler.config.event_duration && scheduler.config.auto_end_date) {

			function _update_minical_select() {
				start_date = scheduler.date.add(inputs[0]._date, selects[0].value, "minute");
				end_date = new Date(start_date.getTime() + (scheduler.config.event_duration * 60 * 1000));

				inputs[1].value = scheduler.templates.calendar_time(end_date);
				inputs[1]._date = scheduler.date.date_part(new Date(end_date));

				selects[1].value = end_date.getHours() * 60 + end_date.getMinutes();
			}

			selects[0].onchange = _update_minical_select; // only update on first select should trigger update so user could define other end date if he wishes too
		}

		function _attach_action(inp, date, number) {
			_init_once(inp, date, number);
			inp.value = scheduler.templates.calendar_time(date);
			inp._date = scheduler.date.date_part(new Date(date));
		}

		_attach_action(inputs[0], ev.start_date, 0);
		_attach_action(inputs[1], ev.end_date, 1);
		_init_once = function() {};

		selects[0].value = ev.start_date.getHours() * 60 + ev.start_date.getMinutes();
		selects[1].value = ev.end_date.getHours() * 60 + ev.end_date.getMinutes();

	},
	get_value: function(node, ev) {
		var inputs = node.getElementsByTagName("input");
		var selects = node.getElementsByTagName("select");

		ev.start_date = scheduler.date.add(inputs[0]._date, selects[0].value, "minute");
		ev.end_date = scheduler.date.add(inputs[1]._date, selects[1].value, "minute");

		if (ev.end_date <= ev.start_date)
			ev.end_date = scheduler.date.add(ev.start_date, scheduler.config.time_step, "minute");
	},
	focus: function(node) {
	}
};
scheduler.linkCalendar = function(calendar, datediff) {
	var action = function() {
		var date = scheduler._date;
		var dateNew = new Date(date.valueOf());
		if (datediff) dateNew = datediff(dateNew);
		dateNew.setDate(1);
		scheduler.updateCalendar(calendar, dateNew);
		return true;
	};

	scheduler.attachEvent("onViewChange", action);
	scheduler.attachEvent("onXLE", action);
	scheduler.attachEvent("onEventAdded", action);
	scheduler.attachEvent("onEventChanged", action);
	scheduler.attachEvent("onAfterEventDelete", action);
	action();
};

scheduler._markCalendarCurrentDate = function(calendar) {
	var date = scheduler._date;
	var mode = scheduler._mode;
	var month_start = scheduler.date.month_start(new Date(calendar._date));
	var month_end = scheduler.date.add(month_start, 1, "month");

	if (mode == 'day' || (this._props && !!this._props[mode])) { // if day or units view
		if (month_start.valueOf() <= date.valueOf() && month_end > date) {
			scheduler.markCalendar(calendar, date, "dhx_calendar_click");
		}
	} else if (mode == 'week') {
		var dateNew = scheduler.date.week_start(new Date(date.valueOf()));
		for (var i = 0; i < 7; i++) {
			if (month_start.valueOf() <= dateNew.valueOf() && month_end > dateNew) // >= would mean mark first day of the next month
				scheduler.markCalendar(calendar, dateNew, "dhx_calendar_click");
			dateNew = scheduler.date.add(dateNew, 1, "day");
		}
	}
};

scheduler.attachEvent("onEventCancel", function(){
	scheduler.destroyCalendar(null, true);
});