import { NgClass } from '@angular/common';
import { Router, RouterLinkActive, RouterLink } from '@angular/router';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { Component, Input, OnInit, AfterViewInit, forwardRef, inject } from '@angular/core';

import { AppComponent } from './app.component';
import { UserService } from '../providers/user/user.service.';
import { MenuItemComponent } from './components/menu/menuitem.component';

@Component({
  standalone: true,
  selector: 'app-menu',
  template: `
        <ul app-submenu [item]="app.grouped ? modelGrouped : modelUngrouped" [root]="true" class="layout-menu"
            [visible]="true" [reset]="reset" [parentActive]="true"></ul>
    `,
  imports: [forwardRef(() => AppSubMenuComponent)]
})
export class AppMenuComponent implements OnInit, AfterViewInit
{
  public app = inject(AppComponent);
  private readonly router = inject(Router);
  private readonly service = inject(UserService);

  public modelGrouped: any[];
  public modelUngrouped: any[];
  @Input() public reset: boolean;
  public isAuthenicated: boolean = false;

  private menuItems: any;

  ngOnInit()
  {
    this.service.authService.sessionEvent.subscribe(value => this.onAuthenication(value));
    if (this.service.authService.currentUserValue)
    {
      this.onAuthenication({ userId: this.service.authService.currentUserValue?.id, loggedIn: true })
    }
    else
    {
      this.app.layoutMode = 'overlay'
    }

    this.reloadMenu();
    this.modelUngrouped = [{ label: 'Main Menu', icon: 'fa fa-home', items: this.modelGrouped }];
  }

  private reloadMenu()
  {
    if (this.isAuthenicated && this.service?.authService?.currentUserValue?.moduleIds)
    {
      const dbOnStartup = this.service.authService.currentUserValue.dbOnStartup;
      this.app.detailInfo = `Version: ${this.app.swVersion} | User: ${this.service.authService.currentUserValue.userName} | Login Time: ${this.service.authService.currentUserValue.loginTime}`;
      this.modelGrouped =
        [
          {
            label: 'Home', icon: 'fa fa-home',
            items:
              [
                { label: 'Logout', icon: 'fa fa-power-off', routerLink: ['/logout'] },
                { label: dbOnStartup ? 'Dashboard' : 'Home', icon: dbOnStartup ? 'fa fa-dashboard' : 'fa fa-home', routerLink: [dbOnStartup ? '/dashboard' : '/home'] }
              ]
          },
        {
          label: 'Activities', icon: 'fa fa-star',
          /*{ label: '<CreateSearchOptionTag>' },*/
          items: this.menuItems?.items ?? []
          }
        ];
    }
    else
    {
      this.app.detailInfo = `Version: ${this.app.swVersion}`;
      this.modelGrouped =
        [
          {
            label: 'Home', icon: 'fa fa-home',
            items: [{ label: 'Login', icon: 'fa fa-sign-in', routerLink: ['/login'] }]
          }];
    }
  }

  ngAfterViewInit()
  {
    setTimeout(() => { this.app.layoutMenuScrollerViewChild.moveBar(); }, 100);
  }

  changeTheme(theme: string, scheme: string)
  {
    const layoutLink: HTMLLinkElement = document.getElementById('layout-css') as HTMLLinkElement;
    const layouthref = layoutLink.baseURI + 'assets/layout/css/layout-' + theme + '.css';
    if (layouthref != layoutLink.href)
    {
      layoutLink.href = 'assets/layout/css/layout-' + theme + '.css';
    }

    const themeLink: HTMLLinkElement = document.getElementById('theme-css') as HTMLLinkElement;
    const themehref = layoutLink.baseURI + 'assets/theme/' + theme + '/theme-' + scheme + '.css';
    if (themehref != themeLink.href)
    {
      themeLink.href = 'assets/theme/' + theme + '/theme-' + scheme + '.css';
    }

    const topbarLogo: HTMLImageElement = document.getElementById('layout-topbar-logo') as HTMLImageElement;
    const menuLogo: HTMLImageElement = document.getElementById('layout-menu-logo') as HTMLImageElement;

    if (theme === 'yellow' || theme === 'lime')
    {
      topbarLogo.src = 'assets/layout/images/logo-black.png';
      menuLogo.src = 'assets/layout/images/logo-black.png';
    }
    else
    {
      topbarLogo.src = 'assets/layout/images/logo-white.png';
      menuLogo.src = 'assets/layout/images/logo-white.png';
    }

    if (scheme === 'dark')
    {
      this.app.darkMenu = true;
    }
    else if (scheme === 'light')
    {
      this.app.darkMenu = false;
    }
  }

  private onAuthenication(value: any): void
  {
    this.isAuthenicated = value.loggedIn;
    if (value.loggedIn && value.userId && value.userId !=0)
    {
      this.service.loadMenu(value.userId).subscribe(
        {
          next: (resp: any) =>
          {
            this.menuItems = resp || [];
            this.app.userId = this.service.authService.currentUserValue?.id;
            this.app.loginId = this.service.authService.currentUserValue?.loginId;
            this.app.layoutMode = this.service.authService.currentUserValue?.menuLayout;
            this.app.notificationCount = this.service.authService.currentUserValue?.notificationCount;
            this.app.autoScrollMenu = (this.app.layoutMode === 'static' || this.app.layoutMode === 'overlay') ? 'auto-scroll-menu' : '';
            this.changeTheme(this.service.authService.currentUserValue?.themeName, this.service.authService.currentUserValue?.schemeName);

            this.reloadMenu();
          },
          error: () =>
          {
            this.menuItems = [];
            this.app.layoutMode = 'overlay'
            this.app.loginId = this.app.autoScrollMenu = '';
            this.app.userId = this.app.notificationCount = 0;

            this.service.authService.loggedout(false);
            this.reloadMenu();

            this.router.navigate(['/login']);
          }
        });
    }
    else
    {
      this.menuItems = [];
      this.app.layoutMode = 'overlay'
      this.app.loginId = this.app.autoScrollMenu = '';
      this.app.userId = this.app.notificationCount = 0;

      this.service.authService.loggedout(false);
      this.reloadMenu();

      this.router.navigate(['/login']);
    }
  }
}

@Component({
  standalone: true,
  selector: 'app-submenu, [app-submenu]',
  template: `
        @for (child of (root ? item : item.items); track child; let i = $index)
        {
          @if (child.visible === false ? false : true)
          {
            <li [ngClass]="{'layout-root-menuitem':root ,'active-menuitem': isActive(i)}" [class]="child.badgeStyleClass">
              @if (root)
              {
                <div>
                  <span class="layout-menuitem-text"><i class="layout-menuitem-icon" [ngClass]="child.icon"></i>&nbsp;&nbsp;{{child.label}}</span>
                </div>
              }
              @if (!child.routerLink)
              {
                @if(child.label.includes('<CreateSearchOptionTag>'))
                {
                  <div class="input-group">
                  <input type="text" maxlength="25" #txtSearch class="form-control form-control-sm" placeholder="Enter Menu Id to run...">
                  <button class="btn btn-sm btn-primary" id="btnSearch" type="button" [disabled]="!txtSearch.value" (click)="onSearchClick(txtSearch.value)"><i class="fa fa-search button-search" aria-hidden="true"></i></button>
                  </div>
                }
                @else
                {
                <a [href]="child.url||'#'" (click)="itemClick($event,child,i)" (mouseenter)="onMouseEnter(i)"
                  [class]="child.styleClass"
                  [attr.tabindex]="!visible ? '-1' : null" [attr.target]="child.target">
                  <i class="layout-menuitem-icon" [ngClass]="child.icon"></i>
                  <span class="layout-menuitem-text">{{child.label}}</span>
                  @if (child.items)
                  {
                    <i class="fa fa-angle-down layout-submenu-toggler"></i>
                  }
                  @if (child.badge)
                  {
                    <span class="menuitem-badge">{{child.badge}}</span>
                  }
                </a>
                }
              }
              @else
              {
                <a (click)="itemClick($event,child,i)" (mouseenter)="onMouseEnter(i)"
                  [routerLink]="child.routerLink" routerLinkActive="active-route" [fragment]="child.fragment"
                  [routerLinkActiveOptions]="{exact: true}" [attr.tabindex]="!visible ? '-1' : null" [attr.target]="child.target">
                  <i class="layout-menuitem-icon" [ngClass]="child.icon"></i>
                  <span class="layout-menuitem-text">{{child.label}}</span>
                  @if (child.items)
                  {
                    <i class="fa fa-angle-down layout-menuitem-toggler"></i>
                  }
                  @if (child.badge)
                  {
                    <span class="menuitem-badge">{{child.badge}}</span>
                  }
                </a>
              }
              <div class="layout-menu-tooltip">
                <div class="layout-menu-tooltip-arrow"></div>
                <div class="layout-menu-tooltip-text">{{child.label}}</div>
              </div>
              @if (child.items)
              {
                <ul app-submenu [item]="child" [visible]="isActive(i)"
                  [reset]="reset" [parentActive]="isActive(i)"
                    [@children]="(app.isSlim() || app.isHorizontal()) && !app.isMobile() && root ? isActive(i) ?
                    'visible' : 'hidden' : isActive(i) ? 'visibleAnimated' :
                    app.grouped===true && root? 'visibleAnimated': 'hiddenAnimated'">
                </ul>
              }
            </li>
          }
        }
        `,
  animations: [
    trigger('children', [
      state('hiddenAnimated', style({
        height: '0px'
      })),
      state('visibleAnimated', style({
        height: '*'
      })),
      state('visible', style({
        height: '*',
        'z-index': 100
      })),
      state('hidden', style({
        height: '0px',
        'z-index': '*'
      })),
      transition('visibleAnimated => hiddenAnimated', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')),
      transition('hiddenAnimated => visibleAnimated', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
    ])
  ],
  imports: [NgClass, RouterLinkActive, RouterLink]
})
export class AppSubMenuComponent
{
  public app = inject(AppComponent);
  public appMenu = inject(AppMenuComponent);

  @Input() item: any;
  @Input() root: boolean;
  @Input() visible: boolean;

  _reset: boolean;
  activeIndex: number;
  _parentActive: boolean;

  private readonly router = inject(Router);

  itemClick(event: Event, item: MenuItemComponent, index: number)
  {
    if (this.root)
    {
      this.app.menuHoverActive = !this.app.menuHoverActive;
    }
    // avoid processing disabled items
    if (item.disabled)
    {
      event.preventDefault();
      return true;
    }

    // activate current item and deactivate active sibling if any
    this.activeIndex = (this.activeIndex === index) ? null : index;

    // execute command
    if (item.command)
    {
      item.command({ originalEvent: event, item });
    }

    // prevent hash change
    if (item.items || (!item.url && !item.routerLink))
    {
      setTimeout(() =>
      {
        this.app.layoutMenuScrollerViewChild.moveBar();
      }, 450);
      event.preventDefault();
    }

    // hide menu
    if (!item.items)
    {
      if (this.app.isHorizontal() || this.app.isSlim())
      {
        this.app.resetMenu = true;
      } else
      {
        this.app.resetMenu = false;
      }

      this.app.overlayMenuActive = false;
      this.app.staticMenuMobileActive = false;
      this.app.menuHoverActive = !this.app.menuHoverActive;
    }
  }

  onMouseEnter(index: number)
  {
    if (this.root && this.app.menuHoverActive && (this.app.isHorizontal() || this.app.isSlim())
      && !this.app.isMobile() && !this.app.isTablet())
    {
      this.activeIndex = index;
    }
  }

  onSearchClick(moduleId: string)
  {
    const item = this.findItemById(moduleId, this.item.items);
    if (item?.routerLink)
    {
      this.router.navigateByUrl(`/${item.routerLink}` );
    }
  }

  private findItemById(moduleId: string, items: any[]): any
  {
    for (const item of items)
    {
      if (item.moduleId === moduleId)
      {
        this.activeIndex = items.indexOf(item);
        return item;
      }

      if (item?.items?.length > 0)
      {
        const foundInChild = this.findItemById(moduleId, item.items);
        if (foundInChild)
        {
          return foundInChild;
        }
      }
    }

    return undefined;
  }

  isActive(index: number): boolean
  {
    return this.activeIndex === index;
  }

  @Input() get reset(): boolean
  {
    return this._reset;
  }

  set reset(val: boolean)
  {
    this._reset = val;
    if (this._reset && (this.app.isHorizontal() || this.app.isSlim()))
    {
      this.activeIndex = null;
    }
  }

  @Input() get parentActive(): boolean
  {
    return this._parentActive;
  }

  set parentActive(val: boolean)
  {
    this._parentActive = val;

    if (!this._parentActive)
    {
      this.activeIndex = null;
    }
  }
}
