import * as DataEvent from '../../src/com/events/DataEvent';
import StringUtils from '../../src/com/utils/StringUtils';
import Settings, { SETTINGS_FILE, SETTINGS_TAG } from './Settings';
import fs from 'fs-extra';
import sanitize from 'sanitize-html';
import Utils from './Utils';
const pug = require('pug');
const md = require('markdown-it')('commonmark');
const _ = require('lodash');
const moment = require('moment');
const settings = new Settings();

export default class Render {
	//--------------------------
	// constructor
	//--------------------------
	constructor() {}
	//--------------------------
	// methods
	//--------------------------
	start() {}

	/**
	 * Renders all pages from markdown to html
	 * @parameter pages: payload for site pages
	 * @parameter theme: current theme being used as defined in settings
	 */
	publishAll(pages, theme, author) {
		return new Promise((resolve, reject) => {
			settings
				.load(SETTINGS_FILE)
				.then(config => {
					let response = [];
					let count = _.filter(pages, page => {
						return page.metadata.deleted === false && page.metadata.published === true;
					}).length;
					let rendered = 0;
					let display_count = 0;
					let recent = [];
					let featured = _.filter(pages, page => {
						return (
							page.metadata.deleted === false &&
							page.metadata.published === true &&
							page.metadata.featured === true
						);
					});
					for (let index = 0; index < pages.length; index++) {
						pages.sort((a, b) => parseFloat(b.metadata.id) - parseFloat(a.metadata.id));
						const page = pages[index];
						if (page.metadata.deleted === false && page.metadata.published === true) {
							if (page.metadata.layout != 'index') {
								if (recent.length < config.global.display_limit) {
									recent.push({
										title: page.metadata.title,
										slug: page.metadata.slug,
										feature: page.metadata.feature,
										created: moment(page.metadata.created).fromNow(),
										path: page.metadata.path
									});
									display_count = ++display_count;
								}
							}

							let writeFile, template;

							let path =
								'public/' +
								moment(page.metadata.created).format('YYYY') +
								'/' +
								moment(page.metadata.created).format('MM') +
								'/';
							if (page.metadata.layout === 'index') {
								template = 'content/themes/' + theme + '/index.pug';
								writeFile = 'public/index.html';
							} else {
								writeFile = path + page.metadata.slug + '.html';
								template = 'content/themes/' + theme + '/page.pug';
							}

							let buffed = sanitize(page.content, {
								allowedTags: ['del', 'a', 'iframe', 'img'],
								allowedAttributes: {
									a: ['href', 'name', 'target'],
									img: ['src'],
									iframe: [
										'height',
										'width',
										'src',
										'frameborder',
										'allow',
										'allowfullscreen'
									]
								}
							});
							let bag = page.metadata.tags.split(',');
							let tags = [];
							for (let index = 0; index < bag.length; index++) {
								let tag = bag[index].trim();
								tags.push({
									label: bag[index],
									slug: new StringUtils().cleanString(tag)
								});
							}
							buffed = new StringUtils().decodeHTML(buffed);
							let html = md.render(buffed, { html: true, xhtmlOut: true });
							let file = pug.renderFile(template, {
								title: page.metadata.title,
								default_bg: page.metadata.feature,
								content: html,
								tags: tags,
								menu: config.menu,
								recent_posts: recent,
								featured_posts: featured,
								meta: {
									who: author,
									when: moment(page.metadata.created).fromNow(),
									tags: tags
								},
								welcome_message: page.metadata.title
							});

							fs.ensureDir(path).then(() => {
								fs.writeFile(writeFile, file, err => {
									// throws an error, you could also catch it here
									if (err) {
										response = {
											type: DataEvent.PAGES_NOT_RENDERED,
											message: err
										};
										reject(response);
									}

									// success case, the file was saved
								});
							});
							rendered = ++rendered;
							if (rendered === count) {
								response = {
									type: DataEvent.PAGES_RENDERED,
									message: 'All Pages Rendered. Sweet.'
								};
								//utils.moveAssets();
								new Utils().moveAssets();
								resolve(response);
							}
						} else {
							if (count === 0) {
								response = {
									type: DataEvent.PAGES_RENDERED,
									message: 'No page rendering needed'
								};
								resolve(response);
							}
							//check to see if deleted pages have been renderered and delete them
							if (page.metadata.layout !== 'index') {
								fs.unlink(
									'public/' +
										page.metadata.path +
										'/' +
										page.metadata.slug +
										'.html'
								)
									.then()
									.catch(() => {
										//console.log('ERROR', err);
									});
							}
						}
					}
				})
				.catch(err => {
					//console.log('ERROR', err);
					reject(err);
				});
		});
	}
	publishTags(pages) {
		let self = this;
		return new Promise((resolve, reject) => {
			self.loadRenderData()
				.then(result => {
					let tags = result.tags.tags;
					let renderList = [];
					for (let index = 0; index < tags.length; index++) {
						let tag = tags[index];
						//console.log('**TAG**', tag.tag_name);
						var pageList = [];
						for (let i = 0; i < pages.length; i++) {
							let page = pages[i];

							//TODO: filter for deleted and unpublished pages
							if (
								page.metadata.deleted === false &&
								page.metadata.published === true
							) {
								if (_.includes(page.metadata.tags, tag.tag_name)) {
									pageList.push({
										title: page.metadata.title,
										slug: page.metadata.slug
									});
								}
							}
						}
						renderList.push({ tag: tag.tag_name, tag_list: pageList, slug: tag.slug });
					}
					let response = [];
					for (let index = 0; index < renderList.length; index++) {
						let item = renderList[index];
						let file = pug.renderFile(
							'content/themes/' + result.settings.global.theme + '/tags.pug',
							{
								title: item.tag,
								default_bg: result.settings.global.background,
								content_tags: 'THESE ARE TAGS',
								tag_list: item.tag_list,
								menu: result.settings.menu
							}
						);
						fs.ensureDir('public/tags', () => {
							fs.writeFile('public/tags/' + item.slug + '.html', file, err => {
								// throws an error, you could also catch it here
								if (err) {
									response = {
										type: DataEvent.TAG_PAGES_NOT_RENDERED,
										message: err
									};
									reject(response);
								}
								// success case, the file was saved
								response = {
									type: DataEvent.TAG_PAGES_RENDERED,
									message: 'Tag Pages ready to go. Good job.'
								};
								resolve(response);
							});
						});
					}
				})
				.catch(err => {
					reject(err);
				});
		});
	}
	publishArchive(archive) {
		settings
			.load(SETTINGS_FILE)
			.then(settings => {
				let file = pug.renderFile(
					'content/themes/' + settings.global.theme + '/archive.pug',
					{
						title: 'ARCHIVES',
						default_bg: settings.global.background,
						content_tags: 'COLD STORAGE',
						archives: archive,
						menu: settings.menu
					}
				);

				fs.writeFile('public/archives.html', file, err => {
					// throws an error, you could also catch it here
					if (err) {
						//console.log('ERROR', err);
						//response = { type: DataEvent.TAG_PAGES_NOT_RENDERED, message: err };
					}
					// success case, the file was saved
				});
			})
			.catch(() => {
				//console.log(err);
			});
	}
	loadRenderData() {
		return new Promise((resolve, reject) => {
			let getSettings = settings.load(SETTINGS_FILE);
			let getTags = settings.load(SETTINGS_TAG);
			Promise.all([getSettings, getTags])
				.then(result => {
					const [settings, tags] = result;
					let data = { settings: settings, tags: tags };
					resolve(data);
				})
				.catch(err => {
					reject(err);
				});
		});
	}

	//--------------------------
	// event handlers
	//--------------------------
}
