import {
  Component,
  OnInit,
  Input,
  ViewChild,
  OnDestroy,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  AfterViewInit,
  ViewRef,
} from '@angular/core';
import { Process } from '../../core/models/process.model';
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import { Store, Select } from '@ngxs/store';
import {
  DeleteProcess,
  PreventProductLoad,
  ChangeCurrentRoute,
  SetProcessNewStatusToFalse,
} from '../../core/store/actions/process.actions';
import { Breadcrumb } from '../../core/models/breadcrumb.model';
import { ProcessDeleteDialogComponent } from '../../modules/process/components/process-delete-dialog/process-delete-dialog.component';
import { Observable, Subject, forkJoin } from 'rxjs';
import { Notify } from '../../core/store/actions/notifier.actions';
import { AddBreadcrumb } from '../../core/store/actions/breadcrumb.actions';
import { takeUntil, map, switchMap, take, distinctUntilChanged, filter } from 'rxjs/operators';
import { SharedSelectors } from '../../core/store/selectors/shared.selectors';
import { ProcessCart } from '../../core/models/process-cart.model';
import { trigger, transition, animate, style, keyframes } from '@angular/animations';
import { AppState } from '../../core/store/state/app.state';
import { AppSetCurrentProcess } from '../../core/store/actions/app.actions';
import { ProcessSelectors } from '../../core/store/selectors/process.selectors';
import { ModuleSwitcher } from '../../core/models/app-switcher.enum';

import { USER_FORM_STATE_KEY, USER_EXTRAS_FORM_STATE_KEY, USER_ERRORS_FORM_STATE_KEY } from '../../core/utils/app.constants';
import { DeleteFormState } from '../../core/store/actions/forms.actions';

@Component({
  selector: 'app-process-tab',
  templateUrl: './process-tab.component.html',
  styleUrls: ['./process-tab.component.scss'],
  animations: [
    trigger('cartnumber', [
      transition('* => delete', [
        animate(
          1000,
          keyframes([
            style({ transform: 'translateY(-60%)', opacity: 0, offset: 0 }),
            style({ transform: 'translateY(10%)', opacity: 1, offset: 0.4 }),
            style({ transform: 'translateY(0%)', opacity: 1, offset: 0.6 }),
            style({ transform: 'translateY(5%)', opacity: 1, offset: 0.8 }),
            style({ transform: 'translateY(0%)', opacity: 1, offset: 0.99 }),
          ])
        ),
      ]),
    ]),
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProcessTabComponent implements OnInit, OnDestroy, AfterViewInit {
  @Input() process: Process;
  @Input() processes: Array<Process>;
  @Input() module: ModuleSwitcher;
  @Input() last = false;
  @Select(ProcessSelectors.getProcesses) procecesses$: Observable<Process[]>;
  @Select(SharedSelectors.getCart) cartData$: Observable<ProcessCart>;
  @Select(SharedSelectors.cartHasDownloadForProcess) cartHasDownloadForProcess$: Observable<{ status: boolean; currentProcessId: number }>;
  @Select(AppState.getCurrentProcessId) currentProcessId$: Observable<number>;
  destroy$ = new Subject();
  @ViewChild('deleteporcessdialog')
  processDeleteDialogComponent: ProcessDeleteDialogComponent;
  cartCount = 0;
  cartanimation = '';
  cartBackgroundForDownload = false;

  constructor(private store: Store, private router: Router, private cdr: ChangeDetectorRef, private route: ActivatedRoute) {}
  isProcessFinished = this.router.url === '/cart/confirmation';

  deleteProcess(process: Process) {
    this.store.dispatch(new DeleteProcess(process));
    this.store.dispatch(new Notify(1));
    const processes = this.store.selectSnapshot(ProcessSelectors.getProcesses) as Process[];
    if (processes) {
      this.processDeleteCleanUp();
      if (processes.length < 1) {
        this.router.navigate(['/dashboard']);
      } else {
        const newSelectedProcess = processes[processes.length - 1];
        if (newSelectedProcess && newSelectedProcess.currentRoute && newSelectedProcess.currentRoute.length > 0) {
          if (newSelectedProcess.currentRoute && newSelectedProcess.currentRouteQueryParams) {
            this.router.navigate([newSelectedProcess.currentRoute], { queryParams: newSelectedProcess.currentRouteQueryParams });
          } else if (newSelectedProcess.currentRoute) {
            this.router.navigate([newSelectedProcess.currentRoute]);
          }
        }
      }
    }
  }

  openDeleteConfirmationDialog() {
    if (this.process.closeDirectlyTab || this.isProcessFinished) {
      this.deleteProcess(this.process);
    } else {
      this.processDeleteDialogComponent.openDialog();
    }
  }

  selectProcess(process: Process): void {
    this.store
      .dispatch(new AppSetCurrentProcess(process.id))
      .pipe(
        take(1),
        switchMap(() => this.store.dispatch(new PreventProductLoad())),
        switchMap(() => this.store.dispatch(new Notify(process.id)))
      )
      .subscribe(() => {
        const currProcess = this.store.selectSnapshot(ProcessSelectors.getCurrentProcess);
        if (currProcess && currProcess.currentRoute && currProcess.currentRoute.length > 0) {
          if (currProcess.currentRoute && currProcess.currentRouteQueryParams) {
            this.router.navigate([currProcess.currentRoute], { queryParams: currProcess.currentRouteQueryParams });
          } else if (currProcess.currentRoute) {
            this.router.navigate([currProcess.currentRoute]);
          }
        }
      });
  }

  ngOnInit() {
    this.store
      .select(SharedSelectors.getCartTabData)
      .pipe(
        takeUntil(this.destroy$),
        map((filterFn) => filterFn(this.process.id))
      )
      .subscribe((quantity: number) => {
        if (quantity < this.cartCount) {
          this.cartanimation = 'delete';
        }

        this.cartCount = quantity;
        this.cdr.detectChanges();
      });

    this.store
      .select(ProcessSelectors.getCurrentRoute)
      .pipe(
        takeUntil(this.destroy$),
        switchMap((route) =>
          this.cartHasDownloadForProcess$.pipe(
            map((data) => {
              return { route: route, data: data };
            })
          )
        )
      )
      .subscribe((result: { route: string; data: { status: boolean; currentProcessId: number } }) => {
        const isCartOpened = result.route === '/cart/review';
        if (result && result.data.currentProcessId === this.process.id && result.data.status && isCartOpened) {
          this.cartBackgroundForDownload = true;
        } else {
          this.cartBackgroundForDownload = false;
        }
        this.detectChanges();
      });
  }

  ngAfterViewInit() {
    setTimeout(() => {
      this.store.dispatch(new SetProcessNewStatusToFalse());
    }, 400);
  }

  ngOnDestroy() {
    this.destroy$.next();
  }

  openCart(process: Process) {
    this.selectProcess(process);
    const newBread: Breadcrumb = {
      name: 'Warenkorb',
      path: '/cart/review',
    };

    this.store.dispatch(new AddBreadcrumb(newBread, 'shoppingCart'));
    this.store.dispatch(new ChangeCurrentRoute('/cart/review'));
    this.router.navigate(['/cart/review']);
  }

  private processDeleteCleanUp() {
    this.store.dispatch(new DeleteFormState(USER_FORM_STATE_KEY));
    this.store.dispatch(new DeleteFormState(USER_EXTRAS_FORM_STATE_KEY));
    this.store.dispatch(new DeleteFormState(USER_ERRORS_FORM_STATE_KEY));
  }

  detectChanges() {
    setTimeout(() => {
      if (this.cdr !== null && this.cdr !== undefined && !(this.cdr as ViewRef).destroyed) {
        this.cdr.detectChanges();
      }
    }, 0);
  }
}
