const objToDom=obj => {
	if(obj instanceof Node) {
		return obj;
	} else if(obj[Popup.EM]) {
		let em=document.createElement('em');
		em.appendChild(document.createTextNode(obj[Popup.EM]));
		return em;
	} else if(obj[Popup.STRONG]) {
		let em=document.createElement('strong');
		em.appendChild(document.createTextNode(obj[Popup.STRONG]));
		return em;
	} else if(typeof obj=='string' || typeof obj=='number') {
		return document.createTextNode(obj+'');
	} else if(Array.isArray(obj)) {
		let ul=document.createElement('ul');
		obj.forEach(elem => ul.appendChild(objToDom(elem)));
		return ul;
	} else {
		let table=document.createElement('table');
		table.classList.add('dual');
		Object
			.keys(obj)
			.forEach(key => {
				let tr=table.appendChild(document.createElement('tr'));
				tr.appendChild(document.createElement('th')).appendChild(document.createTextNode(key));
				tr.appendChild(document.createElement('td')).appendChild(objToDom(obj[key]));
			});
		return table;
	}
}

class Popup {
	constructor(title, content=[], buttons={}, large=false) {
		this.title=title;
		this.content=content.map(objToDom);
		this.buttons={...buttons};
		this.large=large;
		this.animation=true;
	}

	addContent(cnt) {
		this.content.push(objToDom(cnt));
	}
	addText(cnt) {
		this.content.push(document.createTextNode(cnt));
	}
	addEm(cnt) {
		this.content.push(objToDom({[Popup.EM]: cnt}));
	}
	addStrong(cnt) {
		this.content.push(objToDom({[Popup.STRONG]: cnt}));
	}
	addHeading(cnt, level=2) {
		let hn=document.createElement('h'+level);
		hn.innerText=cnt;
		this.content.push(hn);
	}
	addTable(data, heading=Object.keys(data)) {
		let table=document.createElement('table');
		table.classList.add('table');
		let thead=table.appendChild(document.createElement('thead'));
		let headingRow=thead.appendChild(document.createElement('tr'));
		heading.forEach(key => {
			let th=headingRow.appendChild(document.createElement('th'));
			th.innerText=key;
		});
		let tbody=table.appendChild(document.createElement('tbody'));
		data.forEach(row => {
			let tr=tbody.appendChild(document.createElement('tr'));
			heading.forEach(key => {
				let td=tr.appendChild(document.createElement('td'));
				td.innerText=row[key];
			});
		});
		this.content.push(table);
	}

	async display(parent=document.body) {
		let outer=document.createElement('div');
		outer.classList.add('popup');
		let popup=outer.appendChild(document.createElement('div'));
		popup.classList.add('content');
		if(this.large) popup.classList.add('large');
		if(this.animation) outer.classList.add('animation');

		let title=popup.appendChild(document.createElement('h1'));
		title.innerText=this.title;

		let contentSection=popup.appendChild(document.createElement('section'));
		this.content.forEach(elem => contentSection.appendChild(elem));

		let buttonSection=popup.appendChild(document.createElement('section'));
		let buttons=Object.keys(this.buttons).map(btn => {
			let button=document.createElement('button');
			button.innerText=this.buttons[btn];
			button.dataset.code=btn;
			return button;
		});
		buttons.forEach(btn => buttonSection.appendChild(btn));

		parent.appendChild(outer);
		Popup.displayed.push(this);

		const btnActions=buttons.map(btn => new Promise(ok => {
			btn.addEventListener('click', e => {
				e.preventDefault();
				return ok(btn.dataset.code);
			});
		}));
		const dismissAction=new Promise(ok => this.dismiss=ok);

		const code=await Promise.race(btnActions.concat([dismissAction]));

		parent.removeChild(outer);
		Popup.displayed.splice(Popup.displayed.indexOf(this), 1);
		return code;
	}
}

Popup.EM=Symbol('EM');
Popup.STRONG=Symbol('STRONG');

Popup.displayed=[];
Popup.dismiss=arg => {
	Popup.displayed.forEach(p => p.dismiss(arg));
};

return module.exports=Popup;
