/**
 * share-price.js
 * display share information
 */
import { format } from 'date-fns'

/**
* Declare constants
*/
const attributeBase = 'data-rs-share-price';

export class SharePrice {

	constructor(element) {
		this.feed = 'https://tools.eurolandir.com/tools/pricefeed/?companycode=nl-rand';
		this.element = element;
		this.getFeed().then((result) => {
			this.result = result;
			this.renderResult();
		}).catch((reason) => {
			console.error(reason);
		})
	}

	get attributes() {
		return {
			value: `${attributeBase}-value`
		}
	}

	get classes() {
		return {
			change: {
				up: 'share-price--change-up',
				down: 'share-price--change-down'
			}
		}
	}

	/**
	 * Get XML feed with share price information
	 * @see https://tools.eurolandir.com/tools/pricefeed/?companycode=nl-rand
	 */
	getFeed() {
		return new Promise((resolve, reject) => {
			const xhr = new XMLHttpRequest();
			xhr.onreadystatechange = () => {
				if (xhr.readyState === 4) {
					if (xhr.status === 200) {
						let result = null;
						// parse to xml
						try {
							const parser = new DOMParser();
							result = parser.parseFromString(xhr.responseText, 'text/xml');
						} catch (error) {
							reject(error);
						}
						resolve(result);
					} else {
						reject(xhr.statusText);
					}
				}
			};
			xhr.open('GET', this.feed, true);
			xhr.send();
		})
	}

	/**
	 * render results to placeholder elements
	 */
	renderResult() {
		const changeValue = this.getResultValue('Change');
		// add class to container if change is up or down
		this.element.classList.add(SharePrice.changeIsUp(changeValue)
			? this.classes.change.up
			: this.classes.change.down);
		// render seperate items
		this.renderResultItem('last', this.getResultValue('Last', SharePrice.formatCurrency));
		const change = `${SharePrice.formatChange(changeValue)} (${this.getResultValue('ChangePercent', SharePrice.formatNumber)} %)`;
		this.renderResultItem('change', change);
		this.renderResultItem('low', this.getResultValue('Low', SharePrice.formatCurrency));
		this.renderResultItem('high', this.getResultValue('High', SharePrice.formatCurrency));
		this.renderResultItem('symbol', this.getResultValue('Symbol'));
		this.renderResultItem('date', this.getResultValue('Date', SharePrice.formatDate));
	}

	/**
	 * get result by given key and format value if formatter function is defined
	 * @param {string} key
	 * @param {function} formatter
	 */
	getResultValue(key, formatter) {
		let value = this.result.getElementsByTagName(key)[0].textContent;
		if (typeof formatter === 'function') {
			value = formatter.call(this, value);
		}
		return value;
	}

	/**
	 * render given result item to mapped placeholder element
	 * @param {string} attributeValue
	 * @param {string} value
	 */
	renderResultItem(attributeValue, value) {
		this.element.querySelector(`[${this.attributes.value}='${attributeValue}']`).innerText = value;
	}

	/**
	 * check if change is up
	 * @param {string} changeValue
	 */
	static changeIsUp(changeValue) {
		return changeValue.indexOf('-') === -1;
	}

	/**
	 * format change
	 * @param {string} value
	 */
	static formatChange(value) {
		const prefix = value.indexOf('-') === -1
			? '+'
			: '';
		return `${prefix} ${SharePrice.formatNumber(value)}`;
	}

	/**
	 * format number
	 * @param {string} value
	 */
	static formatNumber(value) {
		return value.substring(0, value.length - 2);
	}

	/**
	 * format currency
	 * @param {string} value
	 */
	static formatCurrency(value) {
		return `€ ${SharePrice.formatNumber(value)}`;
	}

	/**
	 * format date
	 * @param {string} value
	 */
	static formatDate(value) {
		value = value.replace(/-/g, '/'); // required for ie11 
		return format(new Date(value), 'D MMM, HH:mm') + ' CET';
	}

	/**
	 * Get selector
	 */
	static getSelector() {
		return `[${attributeBase}]`;
	}

}
