import { bindable, BindingEngine, bindingMode, computedFrom, customElement, Disposable } from "aurelia-framework";
import { UIInternal } from "../../utils/ui-internal";


@customElement("ui-sidebar")
export class UISidebar {
  @bindable()
  public position: "start" | "end" = "start";
  @bindable()
  public width: string = "24rem";
  @bindable()
  public maxWidth: string = "40vw";
  @bindable()
  public minWidth: string = "4rem";

  @bindable()
  public titleBg: string;
  @bindable()
  public titleColor: string;
  @bindable()
  public titleWeight: string;

  @bindable()
  public align: "top" | "bottom" = "top";
  @bindable()
  public headTrigger: "peek" | "toggle" = "peek";

  @bindable({ defaultBindingMode: bindingMode.twoWay })
  public collapsed: boolean = false;

  @bindable()
  public label: string;

  @bindable()
  public labels: Array<LabelMenu>;

  @bindable({ defaultBindingMode: bindingMode.twoWay })
  public currentLabelSelected: LabelMenu;

  protected peek: boolean = false;
  protected resizeable: boolean = false;
  protected collapsible: boolean = false;
  protected closeOnClick: boolean = false;

  private readonly obClick;
  private bodyEl;
  private startX: number = 0;
  private isResizing: boolean = false;
  private disposable: Disposable[];

  constructor(protected element: Element, private bindingEngine: BindingEngine) {
    this.resizeable = element.hasAttribute("resizeable");
    this.collapsible = element.hasAttribute("collapsible");
    this.closeOnClick = element.hasAttribute("close-on-click") && !isFalse(element.getAttribute("close-on-click"));

    this.obClick = UIInternal.subscribe(UIInternal.EVT_VIEWPORT_CLICK, target =>
      !this.peek || (!this.closeOnClick && hasParent(target, "ui-sidebar__body", "ui-sidebar"))
        ? undefined
        : UIInternal.queueTask(() => (this.peek = false))
    );
    this.disposable = new Array<Disposable>();
  }

  bind() {
    this.convertLabel();
    this.getLastLabel();
    if (this.labels != null) {
      this.disposable.push(
        this.bindingEngine.collectionObserver(this.labels).subscribe(changeRecords => {
          this.getLastLabel();
        })
      );
    }
  }
  labelChanged(newValue, oldValue) {
    if (newValue != oldValue) {
      if (oldValue != null && this.labels != null) {
        let oldLabel = this.labels.find(x => x.uniqueIdentifiant == oldValue);
        if (oldLabel != null) {
          this.labels.remove(oldLabel);
        }
      }
      this.convertLabel();
    }
  }

  convertLabel() {
    if (this.label != null) {
      this.labels = [];
      this.labels.push({
        name: this.label,
        isSelected: true,
        uniqueIdentifiant: this.label
      });
    }
  }

  currentLabelSelectedChanged(newValue, oldValue) {
    if (newValue == undefined) {
      this.currentLabelSelected = this.labels?.last();
    }
  }

  getLastLabel() {
    if (this.labels?.find(x => x.isSelected == true) == null) {
      if (this.labels?.length > 0) {
        this.labels.last().isSelected = true;
      }
    }
    this.currentLabelSelected = this.labels?.find(x => x.isSelected);
  }

  protected detached(): void {
    if (this.obClick) {
      this.obClick.dispose();
    }
  }

  @computedFrom("collapsed", "position")
  get toggleIcon() {
    return `${this.collapsed ? "expand" : "collapse"}-${this.position}`;
  }

  protected startResize($event: MouseEvent): void {
    if ($event.button === 0 && !this.isResizing) {
      this.startX = $event.x || $event.clientX;
      this.isResizing = true;

      document.addEventListener("mousemove", this.doResize);
      document.addEventListener("mouseup", this.endResize);
      $event.stopEvent();
    }
  }

  protected resize($event: MouseEvent): void {
    if (this.isResizing) {
      let diff = ($event.x || $event.clientX) - this.startX;
      if (this.position === "end") {
        diff = -1 * diff;
      }
      if (isRtl(this.element)) {
        diff = -1 * diff;
      }
      const newWidth = this.bodyEl.offsetWidth + diff;
      if (newWidth <= (this.maxWidth == "none" ? Number.MAX_SAFE_INTEGER : convertToPx(this.maxWidth)) && newWidth >= convertToPx(this.minWidth)) {
        this.width = newWidth + "px";
        this.startX = $event.x || $event.clientX;
      }
      $event.stopEvent();
    }
  }

  protected stopResize(): void {
    this.isResizing = false;
    document.removeEventListener("mousemove", this.doResize);
    document.removeEventListener("mouseup", this.endResize);
    this.element.dispatchEvent(UIInternal.createEvent("resizeEnd"));
  }

  private doResize = e => this.resize(e);
  private endResize = () => this.stopResize();

  public selected(labelMenu: LabelMenu) {
    this.labels.forEach(x => x.isSelected = false);
    labelMenu.isSelected = true;
    this.currentLabelSelected = labelMenu;
    if (this.collapsible && this.collapsed) {
      this.collapsed = false;
    }
  }
}

export class LabelMenu {
  name: string;
  isSelected: boolean;
  uniqueIdentifiant: string;
}