import { Component, ChangeDetectionStrategy, ChangeDetectorRef, ViewEncapsulation, inject } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { tap, take, catchError, switchMap, filter, shareReplay } from 'rxjs/operators';
import { of, BehaviorSubject, Subject } from 'rxjs';
import { process, State } from '@progress/kendo-data-query';
import { PriceIndexPublicationService } from './price-index-publication.service';
import { MessageService } from '../_shared/services/message.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DialogService, DialogSettings } from '@progress/kendo-angular-dialog';
import { NotifyService } from '../_shared/services/notify.service';
import * as util from '../_shared/utils/util';
import { CellClickEvent, GridDataResult } from '@progress/kendo-angular-grid';
import { FAST_KENDO_COMMON, FAST_PAGE_COMMON } from '../app.config';
import { FastButtonComponent } from "../_shared/elements/fast-button.component";
import { FastWindowComponent } from "../_shared/elements/fast-window.component";
import { FastTextboxComponent } from "../_shared/elements/fast-textbox.component";
import { FastHRComponent } from "../_shared/elements/fast-hr.component";
import { FastHeaderComponent } from "../_shared/elements/fast-header.component";
import { FastLabelComponent } from "../_shared/elements/fast-label.component";

@Component({
  selector: 'app-price-index-publication',
  templateUrl: './price-index-publication.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  imports: [FAST_PAGE_COMMON, FAST_KENDO_COMMON, FastButtonComponent, FastWindowComponent, FastTextboxComponent, FastHRComponent, FastHeaderComponent, FastLabelComponent]
})
export class PriceIndexPublicationComponent {
  private messageService = inject(MessageService);
  private titleService = inject(Title);
  private priceIndexPublicationService = inject(PriceIndexPublicationService);
  private fb = inject(FormBuilder);
  private ref = inject(ChangeDetectorRef);
  private dialogService = inject(DialogService);
  private notify = inject(NotifyService);


  util = util;
  icons = util.icons;

  loading: boolean = true;

  formEditor: FormGroup;
  editorOpened: boolean = false;

  //this needs to be observable for filterIdNames
  editorLoading$ = new BehaviorSubject<boolean>(true);

  state: State = {
    filter: null,
    group: null,
    skip: 0,
    sort: [{ field: 'name', dir: 'asc' }],
    take: 100
  };

  constructor() {
    const fb = this.fb;

    this.formEditor = fb.group({
      id: [null, Validators.required],
      name: [null, Validators.required]
    });
  }

  refreshItems$ = new BehaviorSubject<string>(null)
  refreshItemDetail$ = new BehaviorSubject<number>(null)

  saveItem$ = new Subject()
  deleteItem$ = new Subject()

  title$ = of('Price Index Publication').pipe(
    tap((title) => util.trySetTitle(this.titleService, title))
  )

  getPopupTopPosition() {
    return util.getPopupTopPosition(166);
  }

  getPopupLeftPosition() {
    return util.getPopupLeftPosition(400);
  }

  allItemsLocal: util.IdName[];
  gridData: GridDataResult;

  items$ = this.refreshItems$.pipe(
    tap(() => {
      this.loading = true
    }),
    switchMap(() => {
      return this.priceIndexPublicationService.getItems();
    }),
    tap((result) => {
      this.allItemsLocal = result;
      this.gridData = process(this.allItemsLocal, this.state);
      this.loading = false;
    }),
    catchError(err => {
      return util.handleError(err, this.messageService)
    })
  )

  itemDetail$ = this.refreshItemDetail$.pipe(
    filter(id => id !== null),
    switchMap(id => {
      return this.priceIndexPublicationService.getItemDetail(id);
    }),
    tap((itemDetail) => {
      this.setEditorItem(itemDetail);
      this.editorFinishedLoading();
    }),
    shareReplay(1),
    catchError(err => {
      return util.handleError(err, this.messageService)
    })
  )

  saveItemResult$ = this.saveItem$.pipe(
    switchMap(() => {
      const itemToSave: util.IdName = this.formEditor.value;
      this.formEditor.disable();
      return this.priceIndexPublicationService.saveItem(itemToSave);
    }),
    tap(() => {
      this.notify.success('save successful');
      this.editorFinishedLoading();
      this.editorOpened = false;
      this.refreshItems$.next(null);
    }),
    catchError(err => {
      return util.handleError(err, this.messageService)
    })
  )

  deleteItemResult$ = this.deleteItem$.pipe(
    switchMap(() => {
      const itemToDelete: util.IdName = this.formEditor.value;
      return this.priceIndexPublicationService.deleteItem(itemToDelete.id);
    }),
    tap(() => {
      this.notify.success('delete successful');
      this.editorFinishedLoading();
      this.editorOpened = false;
      this.refreshItems$.next(null);
    }),
    catchError(err => {
      return util.handleError(err, this.messageService)
    })
  )

  setEditorItem(editorItem: util.IdName): void {
    this.formEditor.setValue(editorItem);
  }

  addItem(): void {
    this.openEditor(0);
    this.editorFinishedLoading();
    util.focusInputTarget();
  }

  editClick(args: CellClickEvent): void {
    this.openEditor(args.dataItem.id);
    this.refreshItemDetail$.next(args.dataItem.id);
  }

  openEditor(id: number): void {
    this.formEditor.disable();
    this.editorLoading$.next(true);
    this.formEditor.reset();

    //set new values for an 'add' action
    this.formEditor.patchValue({ id: id });

    this.editorOpened = true;
  }

  editorFinishedLoading(): void {
    this.editorLoading$.next(false);
    this.formEditor.enable();
  }

  saveItem(): void {
    this.formEditor.markAllAsTouched();
    if (this.formEditor.valid) {
      this.editorLoading$.next(true);
      this.saveItem$.next(null);
    } else {
      this.notify.error("validation failed");
    }
  }

  deleteItem(): void {
    const deleteConfirmSettings: DialogSettings = {
      title: "Please confirm",
      content: "Are you sure you want to delete this publication?",
      actions: [{ text: 'No' }, { text: 'Yes', cssClass: 'k-primary' }],
      cssClass: 'utilPrompt'
    }

    this.dialogService.open(deleteConfirmSettings).result.pipe(take(1)).subscribe(result => {
      if (util.getDialogAction(result) === util.dialogAction.Yes) {
        this.formEditor.disable();
        this.editorLoading$.next(true);
        this.deleteItem$.next(null);
      }
    });
  }

  dataStateChange(state: State): void {
    this.state = state;
    this.gridData = process(this.allItemsLocal, this.state);
  }
}
