// angular
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { FormBuilder } from '@angular/forms';
import { FormGroup } from '@angular/forms';
import { Validators } from '@angular/forms';
import { Input } from '@angular/core';
import { Output } from '@angular/core';
import { EventEmitter } from '@angular/core';
import { ViewChild } from '@angular/core';
import { ElementRef } from '@angular/core';

// libs
import * as moment from 'moment';
import Swal from 'sweetalert2';
import { Observable } from 'rxjs';
import { pulseAnimation } from 'angular-animations';

// app
import { ApiRoutes } from '../../api-routes';
import { AccountModel } from '../../model/account.model';
import { MotionModel } from '../../model/motion.model';
import { ItemModel } from '../../model/item.model';
import { atLeastOneNumber } from '../../core/validators/atleastonenumber.validator';

@Component({
	selector: 'account-motion',
	templateUrl: './motion.component.html',
	styleUrls: ['./motion.component.scss'],
	animations: [
		pulseAnimation({ direction: '<=>', duration: 200 }),
	],
})
export class MotionComponent {
	public form!: FormGroup;
	public errorMessage?: string;
	public filteredItems: ItemModel[] = [];
	public option?: string;
	public selectedItem?: ItemModel;
	public inProgress: boolean = false;

	@Input('motion') motion!: MotionModel;
	@Input('account') account!: AccountModel;

	@Output() onAdd: EventEmitter<MotionModel[]> = new EventEmitter<MotionModel[]>();
	@Output() onDelete: EventEmitter<MotionModel> = new EventEmitter<MotionModel>();

	@ViewChild('motionInput') motionInput?: ElementRef;
	@ViewChild('dateInput') dateInput?: ElementRef;

	constructor(
		private fb: FormBuilder,
		private httpClient: HttpClient,
	) {
	}

	ngOnInit(): void {
		this.form = this.fb.group({
			id: [
				this.motion.id,
			],
			date: [
				this.motion.date,
				[Validators.required],
			],
			item: [
				this.motion.item,
				[Validators.required],
			],
			description: [
				this.motion.description,
			],
			plus: [
				this.motion.plus,
			],
			minus: [
				this.motion.minus,
			],
		}, {
			validator: atLeastOneNumber(Validators.required, ['plus', 'minus'])
		});

		this.form.controls['item'].valueChanges.subscribe(value => {
			if (!value) {
				return;
			}

			this.selectedItem = undefined;

			this.httpClient
				.get<ItemModel[]>(ApiRoutes.Items + '?term=' + encodeURIComponent(value))
				.subscribe(x => {
					this.filteredItems = x;
				});
		});

		this.form.valueChanges.subscribe(val => {
			this.form.controls['plus'].markAsPristine();
			this.form.controls['plus'].markAsUntouched();
			this.form.controls['plus'].setErrors(null);
			this.form.controls['minus'].markAsPristine();
			this.form.controls['minus'].markAsUntouched();
			this.form.controls['minus'].setErrors(null);
		});
	}

	displayFn(item: any): string {
		var value = item && item.name ? item.name : item;
		return value;
	}

	selectedFn(item: ItemModel) {
		this.selectedItem = item;
	}

	add() {
		this.form.markAllAsTouched();

		if (this.form.hasError('atLeastOne')) {
			this.form.get('plus')!.setErrors(this.form.errors);
			this.form.get('minus')!.setErrors(this.form.errors);
			return;
		}

		if (!this.form.valid) {
			return;
		}

		this.setInProgress();

		var data: MotionModel = {
			description: this.form.value.description,
			plus: this.form.value.plus || 0,
			minus: this.form.value.minus || 0,
		};

		if (this.form.value.item.name) {
			data.date = this.form.value.date;
			data.item = this.form.value.item.name;
			data.itemId = this.form.value.item.id;
			data.accountId = this.form.value.item.accountId;
			data.amountBalancing = data.plus! > 0 ? data.plus : data.minus;
		} else {
			data.item = this.form.value.item;
		}

		this.httpClient
			.post<MotionModel[]>(ApiRoutes.Motions.replace(':id', this.account.id!), data)
			.subscribe(response => {
				this.onAdd?.emit(response);

				this.form.patchValue({
					item: '',
					plus: 0,
					minus: 0,
				});

				this.filteredItems = [];
				this.motionInput?.nativeElement.focus();
				this.form.markAsUntouched();
				this.setInProgress(false);
			}, error => {
				this.errorMessage = error.detail;
				this.setInProgress(false);
			});
	}

	private setInProgress(inProgress: boolean = true) {
		this.inProgress = inProgress;
	}

	update() {
		this.form.markAllAsTouched();

		if (!this.form.valid) {
			if (this.form.hasError('atLeastOne')) {
				this.form.get('plus')!.setErrors(this.form.errors);
				this.form.get('minus')!.setErrors(this.form.errors);
			}
			return;
		}

		this.setInProgress();

		var url = ApiRoutes.Motion
			.replace(':id', this.account.id!)
			.replace(':motionId', this.motion.id!);

		var data = this.form.value;
		data.motion = data.item.name
			? data.item.name
			: data.motion;
		data.itemId = this.selectedItem?.id;

		this.httpClient
			.put<MotionModel>(url, data)
			.subscribe(response => {
				this.form.markAsUntouched();
				this.setInProgress(false);
			}, error => {
				this.errorMessage = error.detail;
				this.setInProgress(false);
			});
	}

	delete() {
		Swal.fire({
			title: 'Delete motion ' + this.motion.item,
			showCancelButton: true,
			confirmButtonText: 'Delete',
			showLoaderOnConfirm: true,
			preConfirm: (name) => {
				return new Promise<MotionModel>((resolve, reject) => {
					var url = ApiRoutes.Motion
						.replace(':id', this.account.id!)
						.replace(':motionId', this.motion.id!);

					this.setInProgress();

					this.httpClient.delete<MotionModel>(url)
						.subscribe(data => {
							resolve(data);
							this.setInProgress(false);
						}, error => {
							Swal.showValidationMessage(error.detail);
							reject();
							this.setInProgress(false);
						});

				}).catch(x => {
					return false;
				});
			},
			allowOutsideClick: () => !Swal.isLoading(),
		}).then((result) => {
			if (result.isConfirmed) {
				this.onDelete?.emit((result.value! as MotionModel));
			}
		});
	}

	import() {

	}

	addDay(days: number) {
		var date = moment(this.form!.get('date')!.value).add(days, 'days').toDate();
		this.form.patchValue({
			date: date,
		});
	}
}
