import {
  Component,
  Input,
  Output,
  EventEmitter,
  ChangeDetectionStrategy,
} from '@angular/core';
import { LogFilter, AliasFilter, AlgoFilter, SymbolFilter } from '@zfl/models';
import { MatCheckboxChange } from '@angular/material/checkbox';
import { trigger, transition, style, animate } from '@angular/animations';
interface Node {
  name: string;
  enabled: boolean;
  expanded?: boolean;
  children?: Node[];
}
@Component({
  selector: 'app-algo-selector',
  templateUrl: './algo-selector.component.html',
  styleUrls: ['./algo-selector.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  animations: [
    trigger('fold', [
      transition(':enter', [
        style({ height: 0, overflow: 'hidden' }),
        animate('.3s ease', style({ height: '*' })),
      ]),
      transition(':leave', [
        style({ height: '*', overflow: 'hidden' }),
        animate('.3s ease', style({ height: 0 })),
      ]),
    ]),
  ],
})
export class AlgoSelectorComponent {
  nodes: Node[];
  animationsDisabled: boolean;
  isDisabled = false;
  @Input() set logFilter(lf: LogFilter) {
    this.isDisabled = true;
    this.nodes = Object.entries(lf.aliases).map(
      (alias) =>
        <Node>{
          name: alias[0],
          enabled: alias[1].enabled,
          expanded: alias[1].expanded,
          children: Object.entries(alias[1].algos).map(
            (algo) =>
              <Node>{
                name: algo[0],
                enabled: algo[1].enabled,
                expanded: algo[1].expanded,
                children: Object.entries(algo[1].symbols).map(
                  (symbol) =>
                    <Node>{
                      name: symbol[0],
                      enabled: symbol[1].enabled,
                    }
                ),
              }
          ),
        }
    );
    setTimeout(() => (this.isDisabled = false), 0);
  }

  @Output() logFilterChange = new EventEmitter<LogFilter>();

  constructor() {}

  handleChange($event: MatCheckboxChange, node: Node, all: boolean = false) {
    if (all || !$event.checked) {
      this.checkNode($event.checked, node);
    }
    node.enabled = $event.checked;
    // this.enableByDescendant(this.nodes);
    const logFilter: LogFilter = {
      aliases: this.nodes.reduce((aliasacc, alias) => {
        aliasacc[alias.name] = {
          enabled: alias.enabled,
          expanded: alias.expanded,
          algos: alias.children.reduce((algoacc, algo) => {
            algoacc[algo.name] = {
              enabled: algo.enabled,
              expanded: algo.expanded,
              symbols: algo.children.reduce((symbolacc, symbol) => {
                symbolacc[symbol.name] = { enabled: symbol.enabled };
                return symbolacc;
              }, <SymbolFilter>{}),
            };
            return algoacc;
          }, <AlgoFilter>{}),
        };
        return aliasacc;
      }, <AliasFilter>{}),
    };
    this.logFilterChange.emit(logFilter);
  }

  toggleExpand($event: MouseEvent, node: Node) {
    $event.stopPropagation();
    node.expanded = !node.expanded;
  }

  private checkNode(checked: boolean, node: Node | undefined) {
    if (!node) {
      return;
    }
    node.children &&
      node.children.forEach((child) => {
        this.checkNode(checked, child);
        child.enabled = checked;
      });
    node.enabled == checked;
  }
}