import * as echarts from 'echarts';
import { uid, debounceByAnimationFrame } from '../../../../utils/utils';
import GlPopover from '../../../base/popover/popover';
import { popoverPlacements } from '../../../../utils/constants';
import { TOOLTIP_LEFT_OFFSET, TOOLTIP_TOP_OFFSET } from '../../../../utils/charts/constants';
import { getTooltipAxisConfig, getTooltipTitle, getTooltipContent, getTooltipParams } from '../../../../utils/charts/config';
import TooltipDefaultFormat from './tooltip_default_format/tooltip_default_format';
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';

var script = {
  name: 'GlChartTooltip',
  components: {
    GlPopover,
    TooltipDefaultFormat
  },
  inheritAttrs: false,
  props: {
    chart: {
      type: Object,
      required: true,
      validator(chart) {
        return Object.is(chart, echarts.getInstanceByDom(chart.getDom()));
      }
    },
    id: {
      type: String,
      required: false,
      default: () => uid()
    },
    /**
     * Position of the popover respective to the chart.
     * Sets the `top` style property.
     */
    top: {
      type: String,
      required: false,
      default: null
    },
    /**
     * Position of the popover respective to the chart.
     * Sets the `bottom` style property.
     */
    bottom: {
      type: String,
      required: false,
      default: null
    },
    /**
     * Position of the popover respective to the chart.
     * Sets the `left` style property.
     */
    left: {
      type: String,
      required: false,
      default: null
    },
    /**
     * Position of the popover respective to the chart.
     * Sets the `right` style property.
     */
    right: {
      type: String,
      required: false,
      default: null
    },
    /**
     * Set to `true` to show, set to `false` to not show.
     * Set to `null` to show only when the mouse is in the chart.
     */
    show: {
      type: Boolean,
      required: false,
      default: null
    },
    /**
     * Popover placement
     */
    placement: {
      type: String,
      required: false,
      default: popoverPlacements.right
    },
    /**
     * Distance between the popover and the pointer when
     * no position is defined
     */
    xOffset: {
      type: Number,
      required: false,
      default: TOOLTIP_LEFT_OFFSET,
      validator(value) {
        // popover target must have a size of at least 1
        return value >= 1;
      }
    },
    /**
     * Distance between the popover and the pointer when
     * no position is defined
     */
    yOffset: {
      type: Number,
      required: false,
      default: TOOLTIP_TOP_OFFSET,
      validator(value) {
        // popover target must have a size of at least 1
        return value >= 1;
      }
    },
    /**
     * Set to true to use the default tooltip formatter.
     */
    useDefaultTooltipFormatter: {
      type: Boolean,
      required: false,
      default: false
    },
    /**
     * Set to true to enable click-to-pin functionality.
     * When enabled, clicking on a chart point will keep the tooltip open, so the user can interact with the tooltip's content.
     * The tooltip will unpin when clicking again on the chart and not on the tooltip.
     */
    clickToPin: {
      type: Boolean,
      required: false,
      default: false
    },
    /**
     * Specifies which axis contains the dimensional data used in the tooltip.
     * When `xAxis`, x-axis value becomes the tooltip's title and
     * y-axis values become the tooltip's values.
     * When `yAxis`, roles are reversed.
     */
    dimensionAxis: {
      type: String,
      required: false,
      default: 'xAxis',
      validator(value) {
        return value === 'xAxis' || value === 'yAxis';
      }
    }
  },
  data() {
    return {
      pointerCoords: null,
      isPointerInChart: false,
      pinnedPosition: null,
      debouncedMouseHandler: debounceByAnimationFrame(this.mouseHandler),
      title: null,
      content: {},
      params: null
    };
  },
  computed: {
    targetId() {
      // if multiple tooltips are used in a chart component,
      // `this.id` can be used to uniquely identify them
      return `${this.chart.getDom().getAttribute('_echarts_instance_')}-tooltip-${this.id}`;
    },
    targetStyle() {
      // the target is a rectangular space between cursor and popover
      return {
        marginTop: `${-this.yOffset}px`,
        height: `${this.yOffset * 2}px`,
        marginLeft: `${-this.xOffset}px`,
        width: `${this.xOffset * 2}px`,
        pointerEvents: this.isPinned ? 'auto' : 'none',
        ...this.tooltipPosition
      };
    },
    fixedPosition() {
      const {
        top,
        left,
        bottom,
        right
      } = this;
      if (top || left || bottom || right) {
        return {
          top,
          left,
          bottom,
          right
        };
      }
      return null;
    },
    tooltipPosition() {
      if (this.fixedPosition) {
        return this.fixedPosition;
      }
      if (this.pinnedPosition) {
        return this.pinnedPosition;
      }
      return this.pointerPosition;
    },
    shouldShowPopover() {
      if (this.show !== null) {
        return this.show;
      }
      return this.isPinned || this.isPointerInChart;
    },
    isPinned() {
      return this.pinnedPosition !== null;
    },
    pointerPosition() {
      if (!this.pointerCoords) {
        return null;
      }
      return {
        left: `${this.pointerCoords.x}px`,
        top: `${this.pointerCoords.y}px`
      };
    }
  },
  created() {
    this.chart.getZr().on('mousemove', this.debouncedMouseHandler);
    this.chart.getZr().on('mouseout', this.debouncedMouseHandler);
    if (this.clickToPin) {
      document.addEventListener('keydown', this.keyDownHandler);
      this.chart.getZr().on('click', this.clickHandler);
    }
    if (this.useDefaultTooltipFormatter) {
      this.chart.setOption({
        [this.dimensionAxis]: {
          axisPointer: {
            show: true,
            label: {
              formatter: params => {
                var _options$this$dimensi, _options$this$dimensi2, _options$valueAxis, _options$valueAxis$;
                const options = this.chart.getOption();
                const {
                  dimensionIndex,
                  metricIndex,
                  valueAxis
                } = getTooltipAxisConfig(this.dimensionAxis);
                const titleAxisName = (_options$this$dimensi = options[this.dimensionAxis]) === null || _options$this$dimensi === void 0 ? void 0 : (_options$this$dimensi2 = _options$this$dimensi[0]) === null || _options$this$dimensi2 === void 0 ? void 0 : _options$this$dimensi2.name;
                const valueAxisName = (_options$valueAxis = options[valueAxis]) === null || _options$valueAxis === void 0 ? void 0 : (_options$valueAxis$ = _options$valueAxis[0]) === null || _options$valueAxis$ === void 0 ? void 0 : _options$valueAxis$.name;
                this.title = getTooltipTitle(params, titleAxisName, dimensionIndex);
                this.content = getTooltipContent(params, valueAxisName, metricIndex);
                this.params = getTooltipParams(params, options);
              }
            }
          }
        }
      });
    }
  },
  beforeDestroy() {
    this.chart.getZr().off('mousemove', this.debouncedMouseHandler);
    this.chart.getZr().off('mouseout', this.debouncedMouseHandler);
    if (this.clickToPin) {
      this.chart.getZr().off('click', this.clickHandler);
      document.removeEventListener('keydown', this.keyDownHandler);
    }
  },
  methods: {
    getEventCoordsWithinChart(_ref) {
      let {
        event
      } = _ref;
      const {
        zrX,
        zrY
      } = event;
      const x = Math.round(zrX);
      const y = Math.round(zrY);
      if (!Number.isFinite(x) || !Number.isFinite(y)) {
        return null;
      }
      if (!this.chart.containPixel('grid', [x, y])) {
        return null;
      }
      return {
        x,
        y
      };
    },
    mouseHandler(event) {
      const coords = this.getEventCoordsWithinChart(event);
      if (!coords) {
        this.isPointerInChart = false;
        return;
      }
      this.pointerCoords = coords;
      this.isPointerInChart = true;
    },
    clickHandler(event) {
      if (!this.getEventCoordsWithinChart(event)) {
        return;
      }
      if (!this.isPinned) {
        this.pinTooltip();
      } else {
        this.unpinTooltip(event.event);
      }
    },
    pinTooltip() {
      this.pinnedPosition = this.pointerPosition;

      // prevents any axis pointers from being moved to a new position, they should also be pinned
      this.chart.setOption({
        tooltip: {
          triggerOn: 'none'
        }
      });
    },
    unpinTooltip() {
      this.pinnedPosition = null;

      // restores the axis pointers to be unpinned and be triggered by mousemove
      this.chart.setOption({
        tooltip: {
          triggerOn: 'mousemove',
          show: false
        }
      });

      // shows the tooltip and axis pointer at the position of the click
      this.chart.dispatchAction({
        type: 'showTip',
        x: this.pointerCoords.x,
        y: this.pointerCoords.y
      });
    },
    keyDownHandler(event) {
      if (event.key === 'Escape' && this.isPinned) {
        this.unpinTooltip();
      }
    }
  }
};

/* script */
const __vue_script__ = script;

/* template */
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (_vm.chart)?_c('div',[_c('div',{staticClass:"gl-chart-tooltip",style:(_vm.targetStyle),attrs:{"id":_vm.targetId}}),_vm._v(" "),_c('gl-popover',_vm._b({attrs:{"show":_vm.shouldShowPopover,"target":_vm.targetId,"container":_vm.targetId,"placement":_vm.placement,"triggers":""},scopedSlots:_vm._u([{key:"title",fn:function(){return [_vm._t("title",function(){return [_vm._v(_vm._s(_vm.title))]},null,{ title: _vm.title, params: _vm.params })]},proxy:true}],null,true)},'gl-popover',_vm.$attrs,false),[_vm._v(" "),_vm._t("default",function(){return [_c('tooltip-default-format',{attrs:{"tooltip-content":_vm.content},scopedSlots:_vm._u([(_vm.$scopedSlots['tooltip-value'])?{key:"tooltip-value",fn:function(scope){return [_vm._t("tooltip-value",null,null,scope)]}}:null],null,true)})]},null,{ content: _vm.content, params: _vm.params })],2)],1):_vm._e()};
var __vue_staticRenderFns__ = [];

  /* style */
  const __vue_inject_styles__ = undefined;
  /* scoped */
  const __vue_scope_id__ = undefined;
  /* module identifier */
  const __vue_module_identifier__ = undefined;
  /* functional template */
  const __vue_is_functional_template__ = false;
  /* style inject */
  
  /* style inject SSR */
  
  /* style inject shadow dom */
  

  
  const __vue_component__ = /*#__PURE__*/__vue_normalize__(
    { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
    __vue_inject_styles__,
    __vue_script__,
    __vue_scope_id__,
    __vue_is_functional_template__,
    __vue_module_identifier__,
    false,
    undefined,
    undefined,
    undefined
  );

export { __vue_component__ as default };
