import { makeAutoObservable } from 'mobx';
export const MENU_ID_SELECTOR = 'menu-x';
export type MenuOpenPosition = 'right' | 'left';

export interface MenuOptions {
  id: string;
  label: string;
  icon?: any;
  iconColor?: string;
  action: () => void;
}

export default class ActionMenu {
  show: boolean;
  options: MenuOptions[];
  y: number;
  x: number;
  width: number;
  removeOnScroll: boolean;
  windowHeight?: number;
  windowWidth?: number;

  constructor() {
    this.show = false;
    this.options = [];
    this.y = 0;
    this.x = 0;
    this.width = 200;
    this.removeOnScroll = false;
    document?.addEventListener('scroll', this.handleScroll);
    makeAutoObservable(this);
  }

  get positionStyles() {
    // if there's enough room to show right
    const x = this.x;
    const y = this.y;

    const menuHeight = this.options.length * 40;
    const heightNeeded = y + menuHeight;
    const hasRoomInTheBottom = heightNeeded < (this.windowHeight || -1);
    // if there's enough room show on top
    if (x + this.width < (this.windowWidth || -1) && hasRoomInTheBottom) {
      return {
        top: y,
        left: x
      };
    }
    // not enough room on them bottom let's adjust
    if (x + this.width < (this.windowWidth || -1) && !hasRoomInTheBottom) {
      return {
        top: y - menuHeight / this.options.length,
        left: x
      };
    }

    return {
      top: y,
      left: x - this.width
    };
  }

  setWindowSize(height: number, width: number) {
    this.windowHeight = height;
    this.windowWidth = width;
  }

  open = (e: React.MouseEvent<HTMLButtonElement>) => {
    this.setX(e.pageX);
    this.setY(e.pageY);
    this.setShow(true);
  };

  setY = (value: number) => {
    this.y = value;
  };

  setX = (value: number) => {
    this.x = value;
  };

  setShow = (value: boolean) => {
    this.show = value;
    if (this.show === true) {
      document?.addEventListener(
        'click',
        this.handleActionMenuClickOutside,
        true
      );
    } else {
      document?.removeEventListener(
        'click',
        this.handleActionMenuClickOutside,
        true
      );
    }
  };

  setOptions = (options: MenuOptions[]) => {
    this.options = options;
  };

  setRemoveOnScroll = (value: boolean) => {
    this.removeOnScroll = value;
  };

  handleActionMenuClickOutside = (e: any) => {
    const elemWrapper = document?.getElementById(MENU_ID_SELECTOR);
    if (!elemWrapper?.contains(e.target)) {
      // clicked outside the menu
      this.setShow(false);
    }
  };

  handleScroll = () => {
    if (this.removeOnScroll) {
      this.setShow(false);
    }
  };
}
export const actionMenu = new ActionMenu();
