import { Component, OnInit, Input, OnDestroy, Output, EventEmitter, ViewChild, ElementRef, HostListener } from '@angular/core';
import { RecommandationService } from '../../core/services/recommandation.service';
import { ItemDTO } from '@swagger/cat';
import { BehaviorSubject, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ChangeCurrentRoute, AddProcess } from '../../core/store/actions/process.actions';
import { Store } from '@ngxs/store';
import { Router } from '@angular/router';
import { RecommendationItem } from '../../core/models/recommendation.model';
import { RecommendationMapping } from '../../core/mappings/recommendation.mapping';
import { ProcessSelectors } from '../../core/store/selectors/process.selectors';
import { Breadcrumb } from '../../core/models/breadcrumb.model';
import { AddBreadcrumb } from '../../core/store/actions/breadcrumb.actions';
import { Process } from '../../core/models/process.model';
import { WindowRef } from '../../core/services/window-ref.service';

@Component({
  selector: 'app-recommendations',
  templateUrl: 'recommendations.component.html',
  styleUrls: ['recommendations.component.scss'],
})
export class RecommendationsComponent implements OnInit, OnDestroy {
  @ViewChild('books', { read: ElementRef, static: true }) public books: ElementRef<any>;
  @Input() book?: ItemDTO;
  @Output() redirect: EventEmitter<number> = new EventEmitter();
  recommendations: RecommendationItem[] = [];
  destroy$ = new Subject();
  bookMapping = new RecommendationMapping();
  bookTitle = '';

  isIPad: boolean;
  private iPadDetected = false;
  private iPadEventRecieved = false;
  showForward = false;
  showForwarContainer = true;
  showBack = false;
  showBackContainer = false;
  offset: number;

  private scrollTimeout;

  constructor(private recoService: RecommandationService, private store: Store, private router: Router, private windowRef: WindowRef) {}

  // deprecated method - invoces call with id
  openBook(bookId: number) {
    const currentRoute = '/product/details/' + bookId;
    this.store.dispatch(new ChangeCurrentRoute(currentRoute));
    this.router.navigate([currentRoute]);

    this.redirect.emit(bookId);
  }

  // current correct implementation - invoces call with ean
  details(ean: string, name: string) {
    const processExist = this.store.selectSnapshot(ProcessSelectors.getProcesses).length > 0;
    if (!processExist) {
      this.createProcess();
    }

    const newBread: Breadcrumb = {
      name: name.substring(0, 12) + (name.length > 12 ? '...' : ''),
      path: '/product/details/' + ean,
      queryParams: { type: 'ean' },
    };

    this.store.dispatch(new AddBreadcrumb(newBread, 'product'));
    this.store.dispatch(new ChangeCurrentRoute('/product/details/' + ean, false, { type: 'ean' }));
    this.router.navigate(['/product/details/' + ean], { queryParams: { type: 'ean' } });
  }

  createProcess() {
    const newProcess = <Process>{
      id: 1,
      name: 'Vorgang 1',
    };
    this.store.dispatch(new AddProcess(newProcess));
  }

  ngOnInit() {
    this.isIPad = this.isIPadEnv();
    if (this.isIPad) {
      this.showForwarContainer = false;
      this.showBackContainer = false;
    }
    if (this.recommendations && this.recommendations.length < 4) {
      this.showForwarContainer = false;
      this.showBackContainer = false;
    }
    this.offset = Math.ceil(this.books.nativeElement.clientWidth / 2);
  }

  public loadReccomendations() {
    if (this.book) {
      this.bookTitle = this.book.product.name;
      const processUniqueIdentifier = this.store.selectSnapshot(ProcessSelectors.getUniqueIdentifier);
      const dig = this.book.ids ? this.book.ids['dig'] : undefined;
      if (dig) {
        this.recoService
          .getRecommandations(processUniqueIdentifier, this.book.ids['dig'])
          .pipe(takeUntil(this.destroy$))
          .subscribe((recommendations: ItemDTO[]) => {
            this.processBooks(recommendations);
          });
      }
    }
  }

  processBooks(recommendations: ItemDTO[]) {
    const items: RecommendationItem[] = [];

    recommendations.forEach((book: ItemDTO) => {
      items.push(this.bookMapping.fromItemDTO(book));
    });

    if (items && items.length > 3) {
      this.showForwarContainer = true;
    }
    this.recommendations = items;
  }

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

  showFowardIcon() {
    if (this.recommendations && this.recommendations.length < 4) {
      return;
    }
    this.showForward = true;
  }

  hideFowardIcon(event) {
    const e = event.toElement || event.relatedTarget;
    if (e && e.classList && (e.classList[0] === 'icon' || e.classList[0] === 'ng-star-inserted')) {
      return;
    }
    this.showForward = false;
  }

  showBackIcon() {
    this.showBack = true;
  }

  hideBackIcon(event) {
    const e = event.toElement || event.relatedTarget;
    if (e && e.classList && (e.classList[0] === 'icon' || e.classList[0] === 'ng-star-inserted')) {
      return;
    }
    this.showBack = false;
  }

  scrollForward() {
    this.books.nativeElement.scrollTo({ left: this.books.nativeElement.scrollLeft + 230, behavior: 'smooth' });
    this.showBack = false;
  }

  scrollBack() {
    this.books.nativeElement.scrollTo({ left: this.books.nativeElement.scrollLeft - 230, behavior: 'smooth' });
    this.showForward = false;
  }

  @HostListener('window:scroll', ['$event'])
  scrollHandler(event) {
    if (this.isIPad) {
      return;
    }
    clearTimeout(this.scrollTimeout);
    this.scrollTimeout = setTimeout(() => {
      this.showBackContainer = this.books.nativeElement.scrollLeft > 0;
      this.showForwarContainer = Math.ceil(this.books.nativeElement.scrollLeft + this.offset * 2) < this.books.nativeElement.scrollWidth;
    }, 200);
  }

  isIPadEnv() {
    const navigator = this.windowRef.nativeWindow.navigator as Navigator;
    const standalone = (navigator as any).standalone,
      userAgent = navigator.userAgent.toLowerCase(),
      ios = /iphone|ipod|ipad/.test(userAgent);

    this.iPadDetected = ios && !standalone;
    return this.iPadDetected || this.iPadEventRecieved;
  }
}
