import { BindingEngine, bindingMode, computedFrom } from "aurelia-binding";
import { bindable, View, ViewCompiler, ViewResources } from "aurelia-templating";
import { Parser } from 'aurelia-binding';
import { Container } from "aurelia-framework";
import { UIInternal } from "../../../utils/ui-internal";
import { DisposableViewModelBase } from '../../../vm/disposable-view-model-base';

export class CommonColumn extends DisposableViewModelBase {
  //header
  @bindable({ defaultBindingMode: bindingMode.toView })
  public headerAlign: "start" | "center" | "end";
  @bindable({ defaultBindingMode: bindingMode.toView })
  public label: string = "";
  @bindable({ defaultBindingMode: bindingMode.toView })
  public title: string;
  @bindable({ defaultBindingMode: bindingMode.toView })
  public dataId: string;

  //cell
  @bindable({ defaultBindingMode: bindingMode.toView })
  public cellAlign: "start" | "center" | "end";
  @bindable
  public css?: object | string;
  @bindable
  public classes: string = '';
  @bindable
  public cellVisible: string;

  @bindable
  public colVisible: boolean;

  @bindable
  public order: 'auto' | number = 'auto';

  @bindable({ defaultBindingMode: bindingMode.toView })
  public validatePropertyName: string | null;

  public templateCell: HTMLTemplateElement;
  public templateHeader: HTMLTemplateElement;

  public sortable: boolean = false;
  public hideOnLarge: boolean = false;
  public hideOnSmall: boolean = false;
  public isRowClickIgnore: boolean;
  public noHeaderOnLarge: boolean = false;
  public noHeaderOnSmall: boolean = false;
  public computedWidth: string;
  public view: View;
  public tableAuTargetId: number;

  constructor(private element: Element, private parser: Parser, private viewCompiler: ViewCompiler, private viewResources: ViewResources, private bindingEngine: BindingEngine) {
    super();
    this.sortable = element.hasAttribute("sortable");
    this.isRowClickIgnore = element.hasAttribute("row-click-ignore");
    this.hideOnLarge = element.hasAttribute("hide-on-large");
    this.hideOnSmall = element.hasAttribute("hide-on-small");
    this.noHeaderOnLarge = element.hasAttribute("no-header") || element.hasAttribute("no-header-on-large");
    this.noHeaderOnSmall = element.hasAttribute("no-header") || element.hasAttribute("no-header-on-small");

    let uiColumnHeader = element.querySelector("ui-column-header");
    if (this.templateHeader == null && uiColumnHeader != null) {
      this.templateHeader = document.createElement("template");
      this.templateHeader.innerHTML = uiColumnHeader.innerHTML;
    }

    if (this.templateCell == null) {
      this.templateCell = document.createElement("template");
      this.templateCell.title = (element as any).outerText.trim();
      if (element.children.length > 0) {
        Array.from(element.children).filter(x => x.localName != "ui-column-header").forEach(c => {
          this.templateCell.innerHTML += c.outerHTML;
        })
      } else {
        this.templateCell.innerHTML = element.innerHTML;
      }
    }
  }

  @computedFrom('colVisible')
  public get isVisible(): boolean {
    return this.colVisible ?? true;
  }

  public colVisibleChanged() {
    UIInternal.broadcast(UIInternal.EVT_UI_TABLE_REFRESH + `_${this.tableAuTargetId}`);
  }

  public cellIsVisible(record: KeyValue) {
    if (this.cellVisible != null) {
      if (typeof (this.cellVisible) == "boolean") {
        return this.cellVisible;
      }
      if (typeof (this.cellVisible) == "string") {
        return this.getResultExpression(this.cellVisible, record);
      }
    }
    return true;
  }

  public getCss(record: KeyValue) {
    if (this.css != null) {
      if (typeof (this.css) == "object") {
        return this.css;
      }
      if (typeof (this.css) == "string") {
        return this.getResultExpression(this.css, record);
      }
    }
    return {};
  }
  public compileCell() {
    const tpl = this.templateCell.outerHTML;
    this.view = this.internalCompileTemplate(tpl);
  }
  protected getResultExpression(expressionText: string, record: KeyValue): any {
    if (expressionText != null && record != null) {
      const expression = this.parser.parse(expressionText);
      const scope = {
        bindingContext: { record: record },
        overrideContext: null
      };
      return expression.evaluate(scope);
    }
  }
  internalCompileTemplate(tpl: string): View {
    const childContainer = Container.instance.createChild();
    const viewFactory = this.viewCompiler
      .compile(tpl, this.viewResources);

    const view = viewFactory.create(childContainer);
    //view.bind(viewModel, bindingContext);
    return view;
  }
}