const obsidian = require('obsidian');
const Plugin = obsidian.Plugin;
const ItemView = obsidian.ItemView;
const getIcon = obsidian.getIcon;
const DateFormat = {
	months: ["januarie", "februarie", "maart", "april", "mei", "juni", "juli", "augustis", "september", "oktober", "november", "december"],
	daysLong: ["Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"],
	week: "y[0-9]{2}w[0-9]{2}",
	days: ["zo", "ma", "di", "wo", "do", "vrij", "za"],
	time: "[0-9]{2}:[0-9]{2}[ap]m",
	date: ""
}
DateFormat.date = "(?:" + DateFormat.week + ")?(?: ?(?:" + DateFormat.days.join('|') + ") ?)?(?:" + DateFormat.time + ")?";
function parseSingleDate(d, defal)
{
	let year = -1, week = -1, dow = -1, time = moment(defal);
	d = d.toLowerCase();
	// year
	let res = d.match(/y([0-9]{2})/);
	if (res !== null)
	{
		year = parseInt(res[1]) + 2000;
	}
	else
	{
		year = defal.isoWeekYear();
	}
	// week
	res = d.match(/w([0-9]{2})/);
	if (res !== null)
	{
		week = parseInt(res[1]);
	}
	else
	{
		week = defal.isoWeek();
	}
	// day of week
	res = d.split(' ');
	for (const p in res)
	{
		let i = DateFormat.days.indexOf(res[p]);
		if (i != -1){
			dow = i;
			break;
		}
	}
	if (dow == -1)
	{
		dow = defal.day()
	}
	// time
	res = d.match(/([0-9]{2}:[0-9]{2}[ap]m)/);
	if (res !== null)
	{
		time = moment(res[1], "hh:mma");
	}
	
	// combine
	time.day(dow);
	time.isoWeek(week);
	time.isoWeekYear(year);
	return time;
}
function stringifySingleDate(date)
{
	let week = date.format("[y]GG[w]WW");
	let dow = DateFormat.days[date.day()];
	let time = date.format("hh:mma");
	return [week, dow, time].join(' ');
}
function stringifyDate(date)
{
	let res = stringifySingleDate(date[0]);
	if (date[1].diff(date[0]) > 1000)
	{
		res += "-" + stringifySingleDate(date[1])
	}
	return res;
}
function parseDate(d, defal)
{
	let start, end;
	let res = d.match(/([^-]+)-([^-]+)/);
	if (res !== null)
	{
		start = parseSingleDate(res[1], defal);
		end = parseSingleDate(res[2], start);
	}
	else
	{
		start = parseSingleDate(d, defal);
		end = start;
	}
	return [start, end]
}
function scanEditor(editor, data)
{
	let lineNum = 0, lineCount = editor.lineCount();
	let defal = parseSingleDate("00:00am", moment());
	while ((lineNum < lineCount))
	{
		let res, line = editor.getLine(lineNum);
		res = line.match("weekboek: \"?(" + DateFormat.date + ")\"?");
		if (res != null)
		{
			defal = parseSingleDate(res[1], defal);
		}
		res = [...line.matchAll("\\[(" + DateFormat.date + "(?:-" + DateFormat.date + ")?)\\]")];
		if (res.length > 0)
		{
			if (res[0][0] == "[-]" && res.length > 1)
			{
				res[0] = res[1];
			}
			if (res[0][0] != "[-]")
			{
				res = res[0]
				res[1] = parseDate(res[1], defal);
				let procesed = processLine(line, line.replace(res[0], ''), res[1], data);
				data = procesed['data'];
				editor.setLine(lineNum, procesed['line']);
			}
		}
		lineNum++;
	}
	return data;
}
function scanFile(content, data)
{
	let lines = content.split('\n');
	let defal = parseSingleDate("00:00am", moment());
	for (let lineNum in lines)
	{
		let res = lines[lineNum].match("weekboek: \"?(" + DateFormat.date + ")\"?");
		if (res != null)
		{
			defal = parseSingleDate(res[1], defal);
		}
		res = [...lines[lineNum].matchAll("\\[(" + DateFormat.date + "(?:-" + DateFormat.date + ")?)\\]")];
		if (res.length > 0)
		{
			if (res[0][0] == "[-]" && res.length > 1)
			{
				res[0] = res[1];
			}
			if (res[0][0] != "[-]")
			{
				res = res[0]
				res[1] = parseDate(res[1], defal);
				let procesed = processLine(lines[lineNum], lines[lineNum].replace(res[0], ''), res[1], data);
				data = procesed['data'];
				lines[lineNum] = procesed['line'];
			}
		}
	}
	return { data: data, content: lines.join('\n') };
}
function processLine(line, noDate, date, data)
{
	let res;
	let item = {
		"id": null,
		"date": stringifyDate(date),
		"title": "Untitled",
		"group": "default",
		"location": "",
		"state": "reminder",
		"type": "reminder"
	};
	// id
	res = noDate.match(/<([a-z0-9]+)\/>/);
	if (res != null)
	{
		item["id"] = res[1];
		noDate = noDate.replace(res[0], '');
	}
	else
	{
		item["id"] = generateId();
		line += " <" + item["id"] + "/>";
	}
	// location
	res = noDate.match(/\{([^\}\{]+)\}/);
	if (res != null)
	{
		item["location"] = res[1];
		noDate = noDate.replace(res[0], '');
	}
	// state (checkbox)
	res = noDate.match(/^[ \t]*- \[(.)\] /);
	if (res != null)
	{
		item['type'] = "task";
		item['state'] = res[1];
		noDate = noDate.replace('[' + res[1] + '] ', '');
	}
	
	noDate = noDate.replace(/[ \t][ \t]+/g, ' '); // remve multeple spaces/tabs in a row
	// title and group
	res = noDate.match(/^ ?- ([^\[\]<>{}]*) - ([^\[\]<>{}]*)/);
	if (res != null)
	{
		item["group"] = res[1];
		item["title"] = res[2];
	}
	else
	{
		// no group look for only title
		res = noDate.match(/^ ?- ([^\[\]<>\{\}]*)/);
		if (res != null)
		{
			item["title"] = res[1];
		}
		else
		{
			item["title"] = noDate;
		}
	}
	// remove leading and ending spaces
	item["title"] = item['title'].replaceAll(/(^ +)?( +$)?/g, '')
	item["group"] = item['group'].replaceAll(/(^ +)?( +$)?/g, '')
	// add/update to database
	if (data == null) data = {};
	data[item["id"]] = item;
	return { line: line, data: data};
}
function generateId()
{
	let id = '';
	const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
	let l = 0;
	while (l < 10) {
	  id += chars.charAt(Math.floor(Math.random() * chars.length));
	  l += 1;
	}
	return id;
}
const VIEW_TYPE_CALENDAR = "fr-calendar"
class CalendarView extends ItemView 
{
	constructor(leaf, plugin)
	{
		super(leaf);
		this.plugin = plugin;
		this.week = stringifySingleDate(moment()).match(DateFormat.week)[0];
		this.zoom = 30/60; // in px/min
	}
	getViewType()
	{
	  return VIEW_TYPE_CALENDAR;
	}
	getDisplayText()
	{
	  return "Calender " + this.week;
	}
	async onOpen()
	{
		const container = this.containerEl.children[1];
		container.empty();
		this.eventsEls = {};
		// mount view
		this.mountView = container.createEl('div', { attr: { style: "height:0" } }).createEl("div", { cls: "frcal__mountView" });
		// month
		this.monthEl = container.createEl("div", { cls: "frcal__month" });
		let today = this.monthEl.createEl("div", { cls: "frcal__time" });
		today.append(getIcon('calendar-days'));
		today.addEventListener('click', function(e) {
			this.gotoThisWeek();
		}.bind(this));
		this.mountFirstEl = this.monthEl.createEl("div", { cls: "frcal__month_first", attr: { style: "flex: 70" } });
		this.mountFirstSpanEl = this.mountFirstEl.createEl("span");
		this.mountSecondEl = this.monthEl.createEl("div", { cls: "frcal__month_second", attr: { style: "flex: 0" } });
		this.mountSecondSpanEl = this.mountSecondEl.createEl("span");
		// day header
		this.headEl = container.createEl("div", { cls: "frcal__days frcal__day_head" });
		this.weekNumEl = this.headEl.createEl("div", { cls: "frcal__time" });
		this.weekNumEl.addEventListener('click', function(e){
			this.openMountView();
		}.bind(this));
		this.dayHeads = [null, null, null, null, null, null, null];
		for (let i = 0; i < 7; i++)
		{
			let dayEl = this.headEl.createEl("div", { cls: "frcal__day frcal__day_head_item" });
			this.dayHeads[i] = dayEl.createEl("span");
		}
		// all day events
		this.alldayEl = container.createEl("div", { cls: "frcal__days frcal__day_allday" });
		this.alldayEl.createEl("div", { cls: "frcal__time" });
		this.allday = [null, null, null, null, null, null, null];
		for (let i = 0; i < 7; i++)
		{
			this.allday[i] = this.alldayEl.createEl("div", { cls: "frcal__day frcal__day_allday_item" });
		}
		// timed events
		this.timedEl = container.createEl("div", { cls: "frcal__days frcal__day_timed" });
		let timed = this.timedEl.createEl("div", { cls: "frcal__time" });
		timed.createEl("div", { cls: "frcal__hour am", text: '12' });
		for (let i = 1; i <= 12; i++)
		{
			timed.createEl("div", { cls: "frcal__hour " + ((i == 12) ? "pm" : "am"), text: i.toString() });
		}
		for (let i = 1; i <= 11; i++)
		{
			timed.createEl("div", { cls: "frcal__hour pm", text: i.toString() });
		}
		this.timed = [null, null, null, null, null, null, null];
		for (let i = 0; i < 7; i++)
		{
			this.timed[i] = this.timedEl.createEl("div", { cls: "frcal__day frcal__timed_item" });
		}
		this.addEvents();
		this.updateWeek();
	}
	openMountView(startMonth = null, endMonth = null)
	{
		this.mountView.empty();
		if (startMonth == null)
		{
			startMonth = moment().subtract(1, "years");
		}
		if (endMonth == null)
		{
			endMonth = moment().add(1, "years");
		}
		if (startMonth.day() != 1)
		{
			if (startMonth.day() == 0)
			{
				startMonth.day(-6);
			}
			else
			{
				startMonth.day(1);
			}
		}
		if (endMonth.day() != 1)
		{
			if (endMonth.day() == 0)
			{
				endMonth.day(-6);
			}
			else
			{
				endMonth.day(1);
			}
		}
		console.log("mount view: start = ", startMonth, "  end = ", endMonth);
		let lastMonth = moment(startMonth).day(4).year() * 12 + moment(startMonth).day(4).month() - 1;
		let table = this.mountView.createEl('table');
		for (let week = moment(startMonth); week < endMonth; week.add(1, "weeks"))
		{
			let date = stringifySingleDate(week).match(DateFormat.week);
			let row = table.createEl("tr", {
				attr: {
					'id': "frcal_mountview_" + date,
					'onclick': "app.workspace.getLeavesOfType('" + VIEW_TYPE_CALENDAR + "')[0].view.mountViewClick('" + date + "')"
				}
			});
			let thursday = moment(week).day(4);
			
			if (lastMonth != thursday.year() * 12 + thursday.month())
			{
				lastMonth += 1;
				let lastDayOfMount = moment(thursday);
				let span = 0;
				while (lastDayOfMount.month() == thursday.month())
				{
					span++;
					lastDayOfMount.add(1, "weeks");
				}
				// let span = moment(week).add(1, "months").date(4).isoWeek() - week.isoWeek();
				row.createEl("td", { attr: { rowspan: span }, cls: 'frcal__month_month' }).innerText = (thursday.month() + 1).toString() + " - " + DateFormat.months[thursday.month()]; 
			}
			row.createEl('td', { cls: 'frcal__weekinmonth' }).innerText = week.isoWeek();
			let day=moment(week)
			for (let i = 7; i > 0; i--)
			{
				let classes = 'frcal__dayinmonth';
				classes += ((day.month()%2 == 1) ? ' frcal__evenMonth' : ' frcal__oddMonth');
				classes += (day.format("y-MM-D") == moment().format("y-MM-D")) ? ' frcal__today' : ''
				row.createEl('td', { cls: classes }).innerText = day.date().toString();
				day.add(1, "day");
			}
		}
		this.mountView.style.display = "block";
		setTimeout(() => {
			document.getElementById('frcal_mountview_' + stringifySingleDate(moment()).match(DateFormat.week)).scrollIntoView({
				behavior: 'instant',
				block: 'center',
				inline: 'center'
			});
		}, 10);
	}
	mountViewClick(week)
	{
		this.mountView.style.display = "none";
		this.gotoThisWeek(week);
	}
 
	async onClose()
	{
	  // Nothing to clean up.
	}
	addEvents()
	{
		this.backButtonEl.ariaDisabled = "false";
		this.backButtonEl.addEventListener('click', this.gotoPreviusWeek.bind(this));
		this.forwardButtonEl.ariaDisabled = "false";
		this.forwardButtonEl.addEventListener('click', this.gotoNextWeek.bind(this));
	}
	gotoPreviusWeek()
	{
		let date = parseSingleDate(this.week + ' ma 12:00am', null).subtract(7, 'days');
		this.week = stringifySingleDate(date).match(DateFormat.week)[0];
		this.updateWeek();
	}
	gotoNextWeek()
	{
		let date = parseSingleDate(this.week + ' ma 12:00am', null).add(7, 'days');
		this.week = stringifySingleDate(date).match(DateFormat.week)[0];
		this.updateWeek();
	}
	gotoThisWeek(week = '')
	{
		if (week == '')
		{
			this.week = stringifySingleDate(moment()).match(DateFormat.week)[0];
		}
		else if (typeof week == 'string')
		{
			// format of this.week is very strikt, this way every format the parser suports will work.
			this.week = stringifySingleDate(parseSingleDate(week, moment())).match(DateFormat.week)[0];
		}
		else
		{
			this.week = stringifySingleDate(week).match(DateFormat.week)[0];
		}
		this.updateWeek();
	}
	updateWeek()
	{
		let monthF = parseSingleDate(this.week + " ma 00:00am",).month();
		this.mountFirstSpanEl.innerText = (monthF+1).toString() + " - " + DateFormat.months[monthF];
		this.weekNumEl.innerHTML = this.week.substring(0, 3) + '
' + this.week.substring(3, 6);
		let zoDate = parseSingleDate(this.week + " zo 00:00am");
		let monthS = zoDate.month();
		if (monthF != monthS)
		{
			this.mountSecondSpanEl.innerText = (monthS+1).toString() + " - " + DateFormat.months[monthS];
			let dow = zoDate.date();
			this.mountFirstEl.setAttr("style", "flex: " + ((7-dow)*10).toString());
			this.mountSecondEl.setAttr("style", "flex: " + ((dow)*10).toString())
		}
		else
		{
			this.mountSecondSpanEl.innerText = "";
			this.mountFirstEl.setAttr("style", "flex: 70")
			this.mountSecondEl.setAttr("style", "flex: 0")
		}
		let today = parseSingleDate("12:00pm", moment());
		for (let day = 0; day < 7; day++)
		{
			let date = parseSingleDate(this.week + " " + DateFormat.days[(day + 1) % 7] + " 12:00pm");
			this.dayHeads[day].innerHTML = DateFormat.daysLong[day] + "
" + date.date().toString();
			if (date.diff(today, "minutes") == 0)
			{
				this.dayHeads[day].style.color = "var(--color-accent)";
			}
			else
			{
				this.dayHeads[day].style.color = "";
			}
		}
		this.updateEvents();
	}
	updateEvents()
	{
		// let item = {
		// 	"id": null,
		// 	"date": stringifyDate(date),
		// 	"allDay": false,
		// 	"title": "Untitled",
		// 	"group": "default",
		// 	"location": null,
		// 	"state": "reminder"
		// };
		// clear events
		let today = parseSingleDate("12:00pm", moment());
		for (let day = 0; day < 7; day++)
		{
			this.allday[day].innerHTML = "";
			this.timed[day].innerHTML = "";
			// add hour lines
			let hourlinesEl = this.timed[day].createEl("div", { cls: "frcal__hourlines" });
			hourlinesEl.createEl("div", { cls: "frcal__hourline", attr: { style: "margin-top: 0px"}  })
			for (let hour = 0; hour < 11; hour++)
			{
				hourlinesEl.createEl("div", { cls: "frcal__hourline", attr: { style: "margin-top: " + (120*this.zoom-1).toString() + "px"}  })
			}
			// add current time line
			if (parseSingleDate(this.week + " " + DateFormat.days[(day+1) % 7] + " 12:00pm").diff(today, "minutes") == 0)
			{
				let time = moment();
				time = time.hour()*60 + time.minute();
				this.timed[day].createEl("div", { cls: "frcal__hourlines" })
						.createEl("div", { cls: "frcal__hourline frcal__now", attr: { style: "top: " + (time*this.zoom-1).toString() + "px"}  })
			}
		}
		let start = parseSingleDate(this.week + " ma 00:00am");
		let end = parseSingleDate(this.week + " zo 11:59pm");
		for (let event in this.plugin.data)
		{
			event = this.plugin.data[event];
			let date = parseDate(event['date'])
			let startInWeek = (date[0] >= start && date[0] <= end);
			let endInWeek = (date[1] >= start && date[1] <= end);
			if (startInWeek && endInWeek)
			{
				let res = [...event.date.matchAll("(?:" + DateFormat.days.join('|') + ")")];
				if ((res.length <= 1) || (res[0][0] == res[1][0]))
				{
					this.renderEvent(event);
				}
				else
				{
					let date_split = event.date.split('-');
					let day_start = DateFormat.days.indexOf(res[0][0]), day_end = DateFormat.days.indexOf(res[1][0]);
					let part = JSON.parse(JSON.stringify(event));
					// first day
					part.date = date_split[0].match(DateFormat.week)[0] + ' ' + DateFormat.days[day_start] + ' ' + date_split[0].match(DateFormat.time)[0];
					part.date += '-' + date_split[1].match(DateFormat.week)[0] + ' ' + DateFormat.days[day_start] + ' 23:59pm';
					this.renderEvent(part);
					// middel days
					for (let day = day_start+1; day < ((day_end == 0) ? 7 : day_end); day++)
					{
						part.date = date_split[0].match(DateFormat.week)[0] + ' ' + DateFormat.days[day] + ' 12:00am';
						part.date += '-' + date_split[1].match(DateFormat.week)[0] + ' ' + DateFormat.days[day] + ' 23:59pm';
						this.renderEvent(part);
					}
					// last day
					part.date = date_split[0].match(DateFormat.week)[0] + ' ' + DateFormat.days[day_end] + ' 12:00am';
					part.date += '-' + date_split[1].match(DateFormat.week)[0] + ' ' + DateFormat.days[day_end] + ' ' + date_split[0].match(DateFormat.time)[0];
					this.renderEvent(part);
				}
			}
			else if (startInWeek || endInWeek)
			{
				console.warn('multi week event not suported', event);
				console.log(date, start, end);
			}
		}
	}
	renderEvent(event)
	{
		let time = parseDate(event.date);
		let container = {}, allDay;
		let day = time[0].day() - 1;
		day = (day == -1) ? 6 : day;
		if (event.date.match(DateFormat.time)[0] == '12:00am')
		{
			container = this.allday[day];
			allDay = true;
		}
		else
		{
			container = this.timed[day];
			allDay = false;
		}
		time[0] = time[0].hour()*60 + time[0].minute();
		time[1] = time[1].hour()*60 + time[1].minute();
		// check for concurrent events
		let classes = "frcal__event";
		for (let i in container.children)
		{
			let child = container.children[i];
			if ((child instanceof HTMLElement) && child.hasClass("frcal__event"))
			{
				if (
					   (time[1] > parseInt(child.dataset.start))
					&& (time[0] < parseInt(child.dataset.end))
				)
				{
					if (time[0] < parseInt(child.dataset.start))
					{
						classes += " frcal__event_concurrent1";
						child.addClass("frcal__event_concurrent2");
					}
					else
					{
						child.addClass("frcal__event_concurrent1");
						classes += " frcal__event_concurrent2";
					}
				}
			}
		}
		let el = container.createEl('div', {
			cls: classes,
			attr: {
				'id': "fr_event_" + event.id,
				'data-group': event.group,
				'data-state': event.state,
				'data-type': event.type,
				'data-start': time[0].toString(),
				'data-end': time[1].toString(),
				'style': ((allDay) ? '' : 'top:' + (time[0]*this.zoom).toString() + 'px')
			},
		});
		let eventEl = el.createEl('span', {
			attr: {
				'style': ((allDay) ? '' : 'min-height:' + ((time[1] - time[0]) * this.zoom).toString() + 'px')
			}
		});
		eventEl.addEventListener('mousedown', (e) => {
			if (e.button == 2)
			{
				this.openMenu(event, {x: e.clientX, y: e.clientY});
			}
		});
		eventEl.addEventListener('touchstart', (e) => {
			if (e.touches.length == 1)
			{
				this.touchEvent = { "event": event, "location": {x: e.touches[0].clientX, y: e.touches[0].clientY}, "time": new Date().getTime() };
				setTimeout(() => {
					if (this.touchEvent != null && ((new Date().getTime() - this.touchEvent.time) > 700))
					{
						this.openMenu(this.touchEvent.event, this.touchEvent.location);
						this.touchEvent = null;
					}
				}, 750);
			}
			else
			{
				this.touchEvent = null;
			}
		});
		eventEl.addEventListener('touchend', (e) => {
			this.touchEvent = null;
		});
		eventEl.addEventListener('touchmove', (e) => {
			this.touchEvent = null;
		});
		switch (event.type)
		{
			case 'task':
				if (event.state == ' ')
				{
					eventEl.createEl('input', {
						cls: 'task-list-item-checkbox',
						attr: {
							'data-task': event.state,
							'type': 'checkbox'
						}
					});
				}
				else
				{
					eventEl.createEl('input', {
						cls: 'task-list-item-checkbox is-checked',
						attr: {
							'data-task': event.state,
							'type': 'checkbox',
							'checked': ''
						}
					});
				}
			default:
				eventEl.appendText(event.title);
				break;
		}
		return el;
	}
	openMenu(event, location)
	{
		let time = [...event.date.matchAll(DateFormat.time)];
		if (time.length == 1)
		{
			time = time[0];
		}
		else if (time.length == 2)
		{
			time = time[0] + "-" + time[1];
		}
		else
		{
			time = "?>";
		}
		let loc = event.location;
		if (loc != "")
		{
			loc = " {" + loc + "}";
		}
		let text = event.group + " " + time + loc;
		let menu = new obsidian.Menu();
		menu.addItem((item) => {
			item.setIsLabel(true);
			item.setTitle(text);
		});
		menu.showAtPosition(location);
	}
}
class FRCalander extends Plugin
{
	async onload()
	{
		this.registerView(VIEW_TYPE_CALENDAR, (leaf) => { return new CalendarView(leaf, this) });
		this.addCommand({
			id: 'fr-calendar-scan',
			name: 'scan active file',
			repeatable: false,
			callback: async () => {
				let file = this.app.workspace.getActiveFile();
				if (file !== null)
				{
					let content = await this.app.vault.read(file);
					let res = scanFile(content, this.data);
					this.data = res.data;
					this.app.vault.modify(file, res.content);
				}
				this.saveData(this.data);
			}
		});
		this.addCommand({
			id: 'fr-calendar-scan-all',
			name: 'scan all files conaining the tag',
			repeatable: false,
			callback: async () => {
				var events = {};
				const notes = this.app.vault.getMarkdownFiles();
				for (const noteFile of notes) {
					const fileCachedData = this.app.metadataCache.getFileCache(noteFile) || {};
					const tags = obsidian.getAllTags(fileCachedData);
					if (tags.contains('#fr-calendar'))
					{
						let content = await this.app.vault.read(noteFile);
						let res = scanFile(content, events);
						events = res.data;
						this.app.vault.modify(noteFile, res.content);
					}
				}
				this.data = events;
				this.saveData(this.data);
			}
		});
		//TODO: scan folder; with DataAdapter
		// this.addCommand({
		// 	id: 'calnder-save',
		// 	name: 'save the calander',
		// 	editorCallback: () => {
		// 		this.saveData(data);
		// 	}
		// });
		// this.addCommand({
		// 	id: 'calnder-load',
		// 	name: 'save the calander',
		// 	editorCallback: () => {
		// 		data = this.loadData();
		// 	}
		// });
		this.addRibbonIcon("calendar", "show fr calender", () => {
			let leaf = app.workspace.getLeavesOfType(VIEW_TYPE_CALENDAR);
			if (leaf.length > 0)
			{
				leaf = leaf[0];
			}
			else
			{
				leaf = app.workspace.getLeavesOfType('empty');
				if (leaf.length > 0)
				{
					leaf = leaf[0];
				}
				else
				{
					leaf = app.workspace.getLeaf('tab');
				}
			}
			leaf.setViewState({ type: VIEW_TYPE_CALENDAR });
			app.workspace.setActiveLeaf(leaf);
		});
		this.data = await this.loadData();
	}
}
module.exports = FRCalander;