import {
  Component,
  OnInit,
  OnDestroy,
  ChangeDetectorRef,
  ChangeDetectionStrategy,
  ViewChild,
  ElementRef,
  AfterViewInit,
} from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { Breadcrumb } from '../../core/models/breadcrumb.model';
import { Process } from '../../core/models/process.model';
import { Store, Select } from '@ngxs/store';
import { ChangeCurrentRoute, ResetProcessProductFilters } from '../../core/store/actions/process.actions';
import { Router } from '@angular/router';
import { takeUntil, switchMap, distinctUntilChanged } from 'rxjs/operators';
import { SharedSelectors } from '../../core/store/selectors/shared.selectors';
import { ResetFilters } from '../../core/store/actions/filter.actions';
import { AppService } from '../../core/services/app.service';
import { ModuleSwitcher } from '../../core/models/app-switcher.enum';
import { BranchProcess } from '../../core/models/branch-process.model';
import { SetBranchProcessCurrentPath } from '../../core/store/actions/branch-process.actions';
import { AppState } from '../../core/store/state/app.state';
import { FILIALE_LANDING_PAGE } from '../../core/utils/app.constants';

@Component({
  selector: 'app-breadcrumbs',
  templateUrl: './breadcrumbs.component.html',
  styleUrls: ['./breadcrumbs.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BreadcrumbsComponent implements OnInit, OnDestroy, AfterViewInit {
  @ViewChild('container', { read: ElementRef })
  public container: ElementRef<any>;
  @Select(SharedSelectors.getBreadcrumbs) breadcrumbs$: Observable<Breadcrumb[]>;
  @Select(SharedSelectors.getCurrentProcess) currentProcess$: Observable<Process>;
  module: ModuleSwitcher;
  destroy$ = new Subject();
  breadcrumbs: Breadcrumb[] = [];
  currentRoute = '';
  start: number;
  end: number;
  breadsCount: number;
  showBack = true;
  showBackNavigationArrow = false;
  showBackArrow = false;
  showForwardNavigationalArrow = false;
  showForrwardArrow = false;
  isIPad = false;

  get firstVisibleItem() {
    if (this.start) {
      return this.start;
    }
    return 0;
  }

  get lastVisibleItem() {
    if (this.end) {
      return this.end;
    }
    return this.breadcrumbs ? this.breadcrumbs.length - 1 : 0;
  }

  get backArrow() {
    return this.router.url.substring(0, 16) === '/product/details' && this.breadsCount > 1;
  }

  get selectedBreadCrumbIndex() {
    if (!this.currentRoute) {
      return 0;
    }
    let route = this.currentRoute;
    const hasParams = this.currentRoute.includes('?');
    if (hasParams) {
      const endOfRouteWithOutParams = this.currentRoute.indexOf('?');
      route = this.currentRoute.substring(0, endOfRouteWithOutParams);
    }
    return this.breadcrumbs.findIndex((t) => t && t.path.indexOf(route) >= 0);
  }

  get lowerMargin() {
    if (this.router.url === '/customer/results') {
      return true;
    }
    if (this.router.url.substring(0, 14) === '/customer/edit') {
      return true;
    }
    if (this.router.url.substring(0, 16) === '/product/details') {
      return true;
    }
    return false;
  }

  constructor(private store: Store, private router: Router, private cdrf: ChangeDetectorRef, private appService: AppService) {}

  getBreadcrumbsFromCurentProcess() {
    this.currentProcess$
      .pipe(
        switchMap((process: Process | BranchProcess) => {
          if (process) {
            this.currentRoute = `${process.currentRoute}`;
            this.cdrf.detectChanges();
          }

          setTimeout(() => {
            this.container.nativeElement.scrollTo({
              left: this.container.nativeElement.scrollWidth,
              behavior: 'smooth',
            });
          }, 400);
          return this.breadcrumbs$;
        }),
        takeUntil(this.destroy$),
        distinctUntilChanged()
      )
      .subscribe((breadcrumbs: Breadcrumb[]) => {
        this.showForwardNavigationalArrow = false;
        this.showBackNavigationArrow = false;
        if (breadcrumbs) {
          const breadName =
            breadcrumbs.length > 0 ? (breadcrumbs[breadcrumbs.length - 1] ? breadcrumbs[breadcrumbs.length - 1].name : '') : '';
          this.showBack = !(breadName === 'Bestellbestätigung' || breadName === 'Remission');
          this.breadcrumbs = breadcrumbs;
          this.breadsCount = Object.keys(this.breadcrumbs) ? Object.keys(this.breadcrumbs).length : 0;
          this.cdrf.detectChanges();
          if (!this.isIPad) {
            setTimeout(() => {
              try {
                this.initNavigationalArrow();
              } catch (error) {}
            }, 1000);
          }
        }
      });
  }

  selectBreadcrumb(breadcrumb: Breadcrumb) {
    if (breadcrumb && breadcrumb.path) {
      if (breadcrumb.path === '/product/search') {
        this.store.dispatch(new ResetFilters());
        this.store.dispatch(new ResetProcessProductFilters());
      }
      if (this.module === ModuleSwitcher.Customer) {
        this.store.dispatch(new ChangeCurrentRoute(breadcrumb.path, true));
      } else {
        this.store.dispatch(new SetBranchProcessCurrentPath(breadcrumb.path, true));
      }
      this.router.navigate([breadcrumb.path], {
        queryParams: breadcrumb.queryParams ? breadcrumb.queryParams : {},
      });
    }
  }

  goBack(breadcrumb: Breadcrumb) {
    if (breadcrumb && breadcrumb.path) {
      if (this.module === ModuleSwitcher.Customer) {
        this.store.dispatch(new ChangeCurrentRoute(breadcrumb.path, false));
        this.router.navigate(['/product/results']);
      } else {
        this.store.dispatch(new SetBranchProcessCurrentPath(breadcrumb.path, false));
        this.router.navigate([FILIALE_LANDING_PAGE]);
      }
    }
  }

  ngOnInit() {
    this.isIPad = this.appService.isIPadEnv();
    this.getBreadcrumbsFromCurentProcess();
    this.store
      .select(AppState.activeModule)
      .pipe(takeUntil(this.destroy$))
      .subscribe((v: ModuleSwitcher) => {
        this.module = v;
        this.cdrf.detectChanges();
      });
  }

  ngAfterViewInit() {
    if (!this.isIPad) {
      setTimeout(() => {
        try {
          this.initNavigationalArrow();
        } catch (error) {}
      }, 100);
    }
  }

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

  addOne() {
    this.breadcrumbs.push({
      name: 'test' + (this.breadcrumbs ? this.breadcrumbs.length : 0),
      path: './i',
    });
  }

  initNavigationalArrow() {
    if (this.container) {
      const containerWidth = this.container.nativeElement.offsetWidth;
      let childrenWidth = 60;
      let elementProcessed = 0;
      if (this.container.nativeElement.children) {
        const breadcrumbs = this.container.nativeElement.children.length - 1;
        for (let i = 0; i < breadcrumbs; i++) {
          elementProcessed++;
          childrenWidth += this.container.nativeElement.children[i].offsetWidth;
        }
        if (breadcrumbs === elementProcessed && containerWidth <= childrenWidth) {
          this.showBackNavigationArrow = true;
          this.cdrf.detectChanges();
        } else {
          this.showBackNavigationArrow = false;
          this.showForwardNavigationalArrow = false;
        }
      }
    }
  }

  showBackNavArrow() {
    this.showBackArrow = true;
  }

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

  hideBackNavArrowIcon() {
    this.showBackArrow = false;
  }

  showForwardNavArrow() {
    this.showForrwardArrow = true;
  }

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

  hideForwardNavArrowIcon() {
    this.showForrwardArrow = false;
  }

  navigateBack() {
    const scrollLeft = this.container.nativeElement.scrollLeft;
    if (scrollLeft <= 121) {
      this.showBackNavigationArrow = false;
    }
    this.container.nativeElement.scrollTo({
      left: scrollLeft - 120,
      behavior: 'smooth',
    });
    this.showForwardNavigationalArrow = true;
    this.cdrf.detectChanges();
  }

  navigateForward() {
    const scrollLeft = this.container.nativeElement.scrollLeft;
    const containerWidth = this.container.nativeElement.offsetWidth;
    const scrollWidth = this.container.nativeElement.scrollWidth;
    if (scrollLeft + 119 + containerWidth <= scrollWidth) {
      this.showForwardNavigationalArrow = false;
    }
    this.container.nativeElement.scrollTo({
      left: scrollLeft + 120,
      behavior: 'smooth',
    });
    this.showBackNavigationArrow = true;
    this.cdrf.detectChanges();
  }
}
