/*
 * https://github.com/morethanwords/tweb
 * Copyright (C) 2019-2021 Eduard Kuzmenko
 * https://github.com/morethanwords/tweb/blob/master/LICENSE
 */

import { attachClickEvent } from "./dom/clickEvent";
import findUpAsChild from "./dom/findUpAsChild";
import EventListenerBase from "./eventListenerBase";
import ListenerSetter from "./listenerSetter";
import IS_TOUCH_SUPPORTED from "../environment/touchSupport";
import safeAssign from "./object/safeAssign";

const KEEP_OPEN = false;
const TOGGLE_TIMEOUT = 200;
const ANIMATION_DURATION = 200;

export default class DropdownHover extends EventListenerBase<{
  open: () => Promise<any> | void,
  opened: () => any,
  close: () => any,
  closed: () => any
}> {
  protected element: HTMLElement;
  protected displayTimeout: number;
  protected forceClose = false;
  protected inited = false;

  constructor(options: {
    element: DropdownHover['element']
  }) {
    super(false);
    safeAssign(this, options);
  }

  public attachButtonListener(button: HTMLElement, listenerSetter: ListenerSetter) {
    let firstTime = true;
    if(IS_TOUCH_SUPPORTED) {
      attachClickEvent(button, () => {
        if(firstTime) {
          firstTime = false;
          this.toggle(true);
        } else {
          this.toggle();
        }
      }, {listenerSetter});
    } else {
      listenerSetter.add(button)('mouseover', (e) => {
        //console.log('onmouseover button');
        if(firstTime) {
          listenerSetter.add(button)('mouseout', this.onMouseOut);
          firstTime = false;
        }

        clearTimeout(this.displayTimeout);
        this.displayTimeout = window.setTimeout(() => {
          this.toggle(true);
        }, TOGGLE_TIMEOUT);
      });
    }
  }

  private onMouseOut = (e: MouseEvent) => {
    if(KEEP_OPEN) return;
    clearTimeout(this.displayTimeout);
    if(!this.isActive()) return;

    const toElement = (e as any).toElement as Element;
    if(toElement && findUpAsChild(toElement, this.element)) {
      return;
    }

    this.displayTimeout = window.setTimeout(() => {
      this.toggle(false);
    }, TOGGLE_TIMEOUT);
  };

  protected init() {
    if(!IS_TOUCH_SUPPORTED) {
      this.element.onmouseout = this.onMouseOut;
      this.element.onmouseover = (e) => {
        if(this.forceClose) {
          return;
        }

        //console.log('onmouseover element');
        clearTimeout(this.displayTimeout);
      };
    }
  }

  public toggle = async(enable?: boolean) => {
    //if(!this.element) return;
    const willBeActive = (!!this.element.style.display && enable === undefined) || enable;
    if(this.init) {
      if(willBeActive) {
        this.init();
        this.init = null;
      } else {
        return;
      }
    }

    if(willBeActive === this.isActive()) {
      return;
    }
    
    if((this.element.style.display && enable === undefined) || enable) {
      const res = this.dispatchResultableEvent('open');
      await Promise.all(res);

      this.element.style.display = '';
      void this.element.offsetLeft; // reflow
      this.element.classList.add('active');

      clearTimeout(this.displayTimeout);
      this.displayTimeout = window.setTimeout(() => {
        this.forceClose = false;
        this.dispatchEvent('opened');
      }, IS_TOUCH_SUPPORTED ? 0 : ANIMATION_DURATION);

      // ! can't use together with resizeObserver
      /* if(isTouchSupported) {
        const height = this.element.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10;
        console.log('[ESG]: toggle: enable height', height);
        appImManager.chat.bubbles.scrollable.scrollTop += height;
      } */

      /* if(touchSupport) {
        this.restoreScroll();
      } */
    } else {
      this.dispatchEvent('close');

      this.element.classList.remove('active');

      clearTimeout(this.displayTimeout);
      this.displayTimeout = window.setTimeout(() => {
        this.element.style.display = 'none';
        this.forceClose = false;
        this.dispatchEvent('closed');
      }, IS_TOUCH_SUPPORTED ? 0 : ANIMATION_DURATION);

      /* if(isTouchSupported) {
        const scrollHeight = this.container.scrollHeight;
        if(scrollHeight) {
          const height = this.container.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10;
          appImManager.chat.bubbles.scrollable.scrollTop -= height;
        }
      } */

      /* if(touchSupport) {
        this.restoreScroll();
      } */
    }

    //animationIntersector.checkAnimations(false, EMOTICONSSTICKERGROUP);
  };

  public isActive() {
    return this.element.classList.contains('active');
  }
}
