import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  EventEmitter,
  Input,
  Optional,
  Output,
  ViewEncapsulation
} from '@angular/core';
import { Router } from '@angular/router';
import { BixiLayoutService } from '../layout.service';
import { IMenu } from '../layout.type';


@Component({
  selector: 'bixi-layout-menu',
  templateUrl: './menu.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  exportAs: 'bixiLayoutMenu',
  host: {
    class: 'bixi-layout-menu',
    '[class.bixi-layout-menu-collapsed]': '!open',
    '[class.bixi-layout-menu-opened]': 'open'
  }
})
export class BixiMenuComponent {
  @Input()
  set menus(menus: IMenu[]) {
    this._menus = menus;
    this.resume();
    this.openCurrentMenu();
  }
  get menus() {
    return this._menus;
  }
  @Output() menuClick = new EventEmitter<IMenu>();
  @Input() singleOpen = false;
  _menus: IMenu[] = [];
  open: boolean = true;
  paddingLeft: number = 22;
  constructor(
    private router: Router,
    @Optional() private cdr: ChangeDetectorRef,
    private layoutService: BixiLayoutService
  ) {
    this.layoutService.openChange.subscribe((open: boolean) => {
      this.open = open;
      if (this.cdr) {
        this.cdr.markForCheck();
      }
    });
  }

  onMenuClick(menuItem: IMenu) {
    this.menuClick.emit({ ...menuItem, selected: true });
  }

  openCurrentMenu() {
    const menus = this.menus.slice();
    const dealData = (dealMenus: IMenu[]): boolean | void => {
      for (const menu of dealMenus) {
        if (menu.link && this.router.isActive(menu.link, !!menu.matchRouterExact)) {
          return true;
        }
        if (menu.children && menu.children.length > 0) {
          if (dealData(menu.children)) {
            menu.open = true;
            return true;
          }
        }
      }
    };
    dealData(menus);
    this._menus = menus;
  }

  onOpenChange(open: boolean, curMenu: IMenu) {
    const menus = this.menus.slice();
    const dealData = (dealMenus: IMenu[]): boolean | void => {
      for (const menu of dealMenus) {
        if (menu._id === curMenu._id) {
          dealMenus.filter((item) => item._id !== curMenu._id).forEach(
            (m) => {
              m.open = false;
            }
          );
          return true;
        }
        if (menu.children && menu.children.length > 0) {
          if (dealData(menu.children)) {
            return true;
          }
        }
      }
    };

    if (open && this.singleOpen) {
      dealData(menus);
      this._menus = menus;
    }
  }

  onToggleClick() {
    this.layoutService.toggleMenu();
  }

  resume() {
    let i = 1;
    const setId = (menus: IMenu[]) => {
      for (const item of menus) {
        item._id = i++;
        if (item.children && item.children.length > 0) {
          setId(item.children);
        }
      }
    };
    setId(this._menus);
  }
}
