import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormlyFieldConfig } from '@ngx-formly/core'
import { ActivatedRoute, Router } from '@angular/router';

import { CrudService } from '../crud.service'
import {BehaviorSubject, NotFoundError} from "rxjs";
import { CrudFormlyJsonschemaService } from "../crud-formly-jsonschema.service";
import {NgbModal} from "@ng-bootstrap/ng-bootstrap";

@Component({
    selector: 'crud-card',
    templateUrl: './card.component.html',
    styleUrls: ['./card.component.css']
})
export class CardComponent implements OnInit {
    @Input() resource: string | undefined;
    @Input() resource_id: string | null = null;
    @Input() schema: string | undefined;
    @Input() is_modal: Boolean = false;

    private _model: {} = {};

    @Input() set model(value: any) {
       this._model = value;
       if (Object.keys(this.form.controls).length) {
           delete value._id;
           this.form.patchValue(value);
       }
    }

    get model(): any {
        return this._model;
    }

    @Output() resourceCreated: EventEmitter<string> = new EventEmitter();
    @Output() resourceUpdated: EventEmitter<string> = new EventEmitter();
    @Output() resourceDeleted: EventEmitter<string> = new EventEmitter();
    @Output() error: EventEmitter<string> = new EventEmitter();
    @Output() resourceReceived: EventEmitter<any> = new EventEmitter();

    form = new FormGroup({});
    fields: FormlyFieldConfig[] = [];

    schemas = JSON.parse(`{}`);

    private _formLoading$ = new BehaviorSubject<boolean>(true);
    private _modelLoading$ = new BehaviorSubject<boolean>(true);

    get formLoading$() {
        return this._formLoading$.asObservable();
    }

    get modelLoading$() {
        return this._modelLoading$.asObservable();
    }

    get submitText() {
        return this.isCreateForm() ? $localize`Create` : $localize`Update`
    }

    constructor(private crudService: CrudService,
                private formlyJsonschema: CrudFormlyJsonschemaService,
                private router: Router,
                private route: ActivatedRoute,
                private modalService: NgbModal,
    ) { }

    ngOnInit(): void {
        this._formLoading$.next(true);
        this._modelLoading$.next(true);
        let fields$;
        if (this.isCreateForm()) {
            this._modelLoading$.next(false);
            fields$ = this.formlyJsonschema.getCreateFields(this.schema!);
        } else {
            this.crudService.get(this.resource!, this.resource_id!).subscribe({
                next :(model: any) => {
                    this.model = model;
                    this._modelLoading$.next(false);
                    this.resourceReceived.emit(model);
                },
                error: (err) => this.error.emit("Error loading the model:" + err)
            });
            fields$ = this.formlyJsonschema.getUpdateFields(this.schema!);
        }

        fields$.subscribe({
            next: (fields: any) => {
                this.fields = [fields];
                this._formLoading$.next(false);
            },
            error: (err) => this.error.emit("Error loading the form:" + err)
        });
    }

  onSubmit(model: any) {
    this._modelLoading$.next(true);
    if (this.isCreateForm()) {
        this.crudService.create(this.resource!, model).subscribe({
            next: (response: any) => {
                this._modelLoading$.next(false);
                if (! this.is_modal) {
                    this.router.navigate([`../${response.id}`], {relativeTo: this.route});
                } else {
                    this.resourceCreated.emit(response.id)
                }
            },
            error: (err) => this.error.emit("Error creating the entity:" + err)
        });
    } else {
        model._id = this.resource_id;
        this.crudService.update(this.resource!, model).subscribe( {
            next: (model: any) => {
                this.resourceUpdated.emit(model._id);
                this.resourceReceived.emit(model);
                this.model = model;
                this._modelLoading$.next(false);
            },
            error: (err) => this.error.emit("Error updating the entity:" + err)
        });
    }
  }

    onDelete() {
        this._modelLoading$.next(true);
        this.model._id = this.resource_id;
        this.crudService.delete(this.resource!, this.model).subscribe({
            next: (model: any) => {
                this._modelLoading$.next(false);
                if (! this.is_modal) {
                    this.router.navigate(['../'], {relativeTo: this.route});
                } else {
                    this.resourceDeleted.emit("")
                }
            },
            error: (err) => this.error.emit("Error deleting the entity:" + err)
        });
    }

    onModelDuplicated(resource_id: string) {
        this.modalService.dismissAll();
    }

    isCreateForm() {
        return this.resource_id === null;
    }

  	open(content: any) {
		this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title' }).result.then(
			(result) => { this.onDelete() },
			(reason) => {},
		);
	}
}
