"use strict";
const codemirror = require("./codemirror.js");
codemirror.CodeMirror.defineOption("info", false, (cm, options, old) => {
  if (old && old !== codemirror.CodeMirror.Init) {
    const oldOnMouseOver = cm.state.info.onMouseOver;
    codemirror.CodeMirror.off(cm.getWrapperElement(), "mouseover", oldOnMouseOver);
    clearTimeout(cm.state.info.hoverTimeout);
    delete cm.state.info;
  }
  if (options) {
    const state = cm.state.info = createState(options);
    state.onMouseOver = onMouseOver.bind(null, cm);
    codemirror.CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
  }
});
function createState(options) {
  return {
    options: options instanceof Function ? { render: options } : options === true ? {} : options
  };
}
function getHoverTime(cm) {
  const { options } = cm.state.info;
  return (options === null || options === void 0 ? void 0 : options.hoverTime) || 500;
}
function onMouseOver(cm, e) {
  const state = cm.state.info;
  const target = e.target || e.srcElement;
  if (!(target instanceof HTMLElement)) {
    return;
  }
  if (target.nodeName !== "SPAN" || state.hoverTimeout !== void 0) {
    return;
  }
  const box = target.getBoundingClientRect();
  const onMouseMove = function() {
    clearTimeout(state.hoverTimeout);
    state.hoverTimeout = setTimeout(onHover, hoverTime);
  };
  const onMouseOut = function() {
    codemirror.CodeMirror.off(document, "mousemove", onMouseMove);
    codemirror.CodeMirror.off(cm.getWrapperElement(), "mouseout", onMouseOut);
    clearTimeout(state.hoverTimeout);
    state.hoverTimeout = void 0;
  };
  const onHover = function() {
    codemirror.CodeMirror.off(document, "mousemove", onMouseMove);
    codemirror.CodeMirror.off(cm.getWrapperElement(), "mouseout", onMouseOut);
    state.hoverTimeout = void 0;
    onMouseHover(cm, box);
  };
  const hoverTime = getHoverTime(cm);
  state.hoverTimeout = setTimeout(onHover, hoverTime);
  codemirror.CodeMirror.on(document, "mousemove", onMouseMove);
  codemirror.CodeMirror.on(cm.getWrapperElement(), "mouseout", onMouseOut);
}
function onMouseHover(cm, box) {
  const pos = cm.coordsChar({
    left: (box.left + box.right) / 2,
    top: (box.top + box.bottom) / 2
  }, "window");
  const state = cm.state.info;
  const { options } = state;
  const render = options.render || cm.getHelper(pos, "info");
  if (render) {
    const token = cm.getTokenAt(pos, true);
    if (token) {
      const info = render(token, options, cm, pos);
      if (info) {
        showPopup(cm, box, info);
      }
    }
  }
}
function showPopup(cm, box, info) {
  const popup = document.createElement("div");
  popup.className = "CodeMirror-info";
  popup.append(info);
  document.body.append(popup);
  const popupBox = popup.getBoundingClientRect();
  const popupStyle = window.getComputedStyle(popup);
  const popupWidth = popupBox.right - popupBox.left + parseFloat(popupStyle.marginLeft) + parseFloat(popupStyle.marginRight);
  const popupHeight = popupBox.bottom - popupBox.top + parseFloat(popupStyle.marginTop) + parseFloat(popupStyle.marginBottom);
  let topPos = box.bottom;
  if (popupHeight > window.innerHeight - box.bottom - 15 && box.top > window.innerHeight - box.bottom) {
    topPos = box.top - popupHeight;
  }
  if (topPos < 0) {
    topPos = box.bottom;
  }
  let leftPos = Math.max(0, window.innerWidth - popupWidth - 15);
  if (leftPos > box.left) {
    leftPos = box.left;
  }
  popup.style.opacity = "1";
  popup.style.top = topPos + "px";
  popup.style.left = leftPos + "px";
  let popupTimeout;
  const onMouseOverPopup = function() {
    clearTimeout(popupTimeout);
  };
  const onMouseOut = function() {
    clearTimeout(popupTimeout);
    popupTimeout = setTimeout(hidePopup, 200);
  };
  const hidePopup = function() {
    codemirror.CodeMirror.off(popup, "mouseover", onMouseOverPopup);
    codemirror.CodeMirror.off(popup, "mouseout", onMouseOut);
    codemirror.CodeMirror.off(cm.getWrapperElement(), "mouseout", onMouseOut);
    if (popup.style.opacity) {
      popup.style.opacity = "0";
      setTimeout(() => {
        if (popup.parentNode) {
          popup.remove();
        }
      }, 600);
    } else if (popup.parentNode) {
      popup.remove();
    }
  };
  codemirror.CodeMirror.on(popup, "mouseover", onMouseOverPopup);
  codemirror.CodeMirror.on(popup, "mouseout", onMouseOut);
  codemirror.CodeMirror.on(cm.getWrapperElement(), "mouseout", onMouseOut);
}
//# sourceMappingURL=info-addon.js.map
