/*
 * Copyright (C) 2018 Robert Bosch GmbH Copyright (C) 2018 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */

import { BreakpointObserver } from '@angular/cdk/layout';
import { AfterViewInit, Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { MatSidenav } from '@angular/material/sidenav';
import { combineLatest, Subject } from 'rxjs';
import { map, startWith, takeUntil } from 'rxjs/operators';
import { BreadcrumbsService } from '../../breadcrumbs.service';
import { BOSCH_BREAKPOINTS } from '../../core-configuration/bosch-breakpoints';
import { MediaQueryBuilder } from '../media-query-builder';
import { BciSidebarService } from './bci-sidebar.service';
import { SidebarNavItem } from './sidebar-nav-item.model';

@Component({
  selector: 'bci-sidebar',
  templateUrl: './bci-sidebar.component.html',
  styleUrls: ['./bci-sidebar.component.scss'],
})
export class BciSidebarComponent implements OnInit, OnDestroy, AfterViewInit {
  @Input() public applicationTitle = '';
  @Input() public sidebarLinks: SidebarNavItem[];
  /**
   * Define media query for sidebar to be hidden.
   * Must be set before first call to getSidebarVisibility to have an effect.
   */
  sidebarVisibilityMediaQuery = MediaQueryBuilder.is().ge(BOSCH_BREAKPOINTS.S).query;
  @ViewChild('sidenav', { static: true }) private sidenav: MatSidenav;
  private open = true;
  private shrinkable = true;
  private visible = true;
  private componentDestroyed$ = new Subject<void>();

  constructor(private sidebarService: BciSidebarService, private breakpointObserver: BreakpointObserver,  public breadcrumbService: BreadcrumbsService) {}

  ngOnInit() {
    const notMobile = this.breakpointObserver.observe(this.sidebarVisibilityMediaQuery).pipe(
      map((result) => result.matches),
      startWith(this.breakpointObserver.isMatched(this.sidebarVisibilityMediaQuery))
    );
    // TODO: remember sidebar state (opened/closed) in storage provider and load here
    combineLatest([this.sidebarService.getSidebarState(), this.sidebarService.getSidebarVisibility(), notMobile])
      .pipe(takeUntil(this.componentDestroyed$))
      .subscribe(([state, visibility, isNotMobile]) => {
        this.open = state;
        this.visible = visibility;
        this.shrinkable = isNotMobile;
        if (this.visible && (this.shrinkable || this.open)) {
          this.sidenav.open();
        } else {
          this.sidenav.close();
        }
      });
  }

  ngOnDestroy() {
    this.componentDestroyed$.next();
    this.componentDestroyed$.complete();
  }

  ngAfterViewInit(): void {
    this.sidenav.openedChange
      .pipe(takeUntil(this.componentDestroyed$))
      .subscribe(() => window.dispatchEvent(new Event('resize')));
  }

  toggleSideNavigationBar() {
    this.sidebarService.setSidebarState(!this.open);
  }

  closeSideNavigationBar() {
    this.sidebarService.setSidebarState(false);
  }

  isOpen(): boolean {
    return this.open;
  }

  isVisible(): boolean {
    return this.visible;
  }

  isShrinkable(): boolean {
    return this.shrinkable;
  }

  isSidebarVisible(): boolean {
    return this.isVisible() && this.isShrinkable();
  }

  isInMobileMode() {
    const isMobile = this.isVisible() && !this.isShrinkable();
    this.breadcrumbService.setShowOrHideBreadcrumbs(isMobile);
    return isMobile;
  }

  sideNavMode() {
    return this.isInMobileMode() ? 'over' : 'side';
  }
}
