Source: scripts/view/balancesView.js

const ChartHandler = require(__dirname + '/../utils/chartHandler.js');
const DateHandler = require(__dirname + '/../utils/dateHandler.js');
const InputHandler = require(__dirname + '/../utils/inputHandler.js');
const View = require(__dirname + '/view.js');

const {timestampToFilename, dateToTimestamp, timestampToString} = require("../utils/dateHandler");

/**
 * Class for controlling the balances page of the application.
 */
class BalancesView extends View {
	/**
	 * @param {Storage} storage Storage object.
	 */
	constructor(storage) {
		super(storage);
	}

	/**
	 * Updates the view.
	 */
	updateView() {
		this.displayOverviewControls();
		this.displayOverview('#mainContent');
	}

	/**
	 * Displays the overview content controls (controls for filtering data).
	 */
	displayOverviewControls() {
		$('#budgetSelect').html(new Option(this.textData['allBudgets'], 'all'));
		this.storage.readMainStorage('budgets').forEach(budget => {
			$('#budgetSelect').append(new Option(budget[0], budget[0]));
		});

		$('#typeSelect #all').text(this.textData['allTypes']);
		$('#nameSearch').prop('placeholder', this.textData['allTransactions']);
		$('#catSearch').prop('placeholder', this.textData['allCategories']);

		$('#dateToDay').val((new Date((new Date()).getFullYear(), (new Date()).getMonth() + 1, 0)).getDate());
		['dateFromMonth', 'dateToMonth'].forEach(id => $(`#${id}`).val((new Date()).getMonth() + 1));
		['dateFromYear', 'dateToYear'].forEach(id => $(`#${id}`).val((new Date()).getFullYear()));
			
		$('#nameSearch').autocomplete({source: this.storage.readMainStorage('availableNames')});
		$('#catSearch').autocomplete({source: this.storage.readMainStorage('availableCategories')});

		$(`#chartTypeSelect option[lang=${this.lang}][value=${this.storage.readPreference('chartType')}]`).prop('selected', true);
		$('#chartTypeSelect').on('change', () => {
			this.storage.storePreference('chartType', $('#chartTypeSelect option:selected').val());
			this.displayOverview('#mainContent');
		});
	}

	/**
	 * Displays the overview, following the selected filters from the controls.
	 */
	displayOverview(id) {
		let budget = $('#budgetSelect option:selected').val();
		let type = $('#typeSelect option:selected').val();
		let amountFrom = $('#amountFrom').val().replace(',', '.');
		let amountTo = $('#amountTo').val().replace(',', '.');
		let name = $('#nameSearch').val();
		let cat = $('#catSearch').val();

		$('#overview-err').html('');

		let input = new InputHandler(this.storage);
		if (!input.isValidAmount(amountFrom, true) || !input.isValidAmount(amountTo, true)
				|| (['dateFromDay', 'dateFromMonth', 'dateFromYear'].some(id => $(`#${id}`).val().trim() !== '') &&
					!input.isValidDate($('#dateFromDay').val(), $('#dateFromMonth').val(), $('#dateFromYear').val()))
				|| (['dateToDay', 'dateToMonth', 'dateToYear'].some(id => $(`#${id}`).val().trim() !== '') &&
					!input.isValidDate($('#dateToDay').val(), $('#dateToMonth').val(), $('#dateToYear').val()))) {
			$('#overview-err').html(this.template.alert(this.textData['invalidSearchCriteria']));
			return;
		}

		let paramList = [];
		if (budget.trim().length > 0 && budget !== 'all') paramList.push(['budget', budget]);
		if (type.trim().length > 0 && type !== 'all')     paramList.push(['type', type]);
		if (name.trim().length > 0)                       paramList.push(['name', name]);
		if (cat.trim().length > 0)                        paramList.push(['category', cat]);

		let quest = paramList.length > 0 ? {
			connector: 'and',
			params: paramList
		} : {
			connector: 'or',
			params: [['type', 'earning'], ['type', 'spending']]
		};

		let startTS = dateToTimestamp($('#dateFromDay').val(), $('#dateFromMonth').val(), $('#dateFromYear').val());
		let start = ['dateFromDay', 'dateFromMonth', 'dateFromYear'].every(id => $(`#${id}`).val().trim() === '') ?
			timestampToFilename((new Date('1970-01-01')).getTime() / 1000) : timestampToFilename(startTS);
		
		let endTS = dateToTimestamp($('#dateToDay').val(), $('#dateToMonth').val(), $('#dateToYear').val());
		let end = ['dateToDay', 'dateToMonth', 'dateToYear'].every(id => $(`#${id}`).val().trim() === '') ?
			timestampToFilename((new Date()).getTime() / 1000) : timestampToFilename(endTS);

		let data = [];
		this.storage.getJsonFiles().forEach(file => {
			if (start.split('.').reverse() <= file.split('.').reverse()
					&& end.split('.').reverse() >= file.split('.').reverse()) {
				data = this.storage.getData(file, quest).filter(e => {
					return (!amountFrom || amountFrom <= e.amount) && (!amountTo || e.amount <= amountTo)
						&& DateHandler.lessEqualDate(new Date(1000 * startTS), new Date(1000 * e.date))
						&& DateHandler.lessEqualDate(new Date(1000 * e.date), new Date(1000 * endTS));
				}).concat(data);
			}
		});

		if (data.length > 0) {
			let total = data.reduce((prev, curr) => prev + parseFloat(curr.amount), 0);
			let tableRows = [[
				this.textData['date'], this.textData['name'], this.textData['amount'],
				this.textData['category'], this.textData['budget'], this.textData['type'],
				this.textData['edit']
			]];

			data.sort((a, b) => a.date < b.date ? 1 : -1).forEach(d => tableRows.push([
				timestampToString(d.date), d.name, this.printNum(d.amount), d.category,
				d.budget, this.textData[d.type], this.elt('button', {
					id: 'btnEditEntry',
					class: 'btn btn-outline-primary',
					onclick: `$('#modalHidden').val('${d.date}')`,
					['data-toggle']: 'modal',
					['data-target']: '#divModal'
				}, this.template.icon('edit', 'black'))
			]));

			$(id).html(this.elt('div', {}, this.template.table(tableRows, {
				id: 'overviewTable'
			}), this.elt('center', {}, `${this.textData['totalSum']}: ${this.printNum(total)}`)));

			$('#overviewTable').children().first().children().first().children().each((index, elem) => {
				if (index <= 5) {
					$(elem).addClass('tableHead');
					$(elem).on('click', () => this.sortTableByColumn('overviewTable', index));
				}
			});

			$('#graphDiv').html(this.elt('canvas', {id: 'graphCanvas', style: 'max-height: 40%; max-width: 75%;'}));
			(new ChartHandler(this)).createChart('#graphCanvas', data);
		} else {
			$(id).html(this.elt('center', {}, this.textData['noTransactions']));
		}
	}
}

module.exports = BalancesView;