function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import polarToSpecialCartesian from "../utils/polarToSpecialCartesian";
import relaxLabelAngles from "./relaxLabelAngles";
import withHover from "../../helperComponents/withHover";
import "./style.css";
import React from "react";
import { cloneDeep, clamp } from "lodash";
var fontWidthToFontSize = 1.75;
var getTextLength = function getTextLength(text) {
  var len = (text || "Unlabeled").length;
  // eslint-disable-next-line no-control-regex
  var nonEnInputReg = /[^\x00-\xff]+/g;
  var nonEnStrings = (text || "Unlabeled").match(nonEnInputReg) || [];
  nonEnStrings.forEach(function (str) {
    return len += str.length * 0.5;
  });
  return len;
};
function Labels(_ref) {
  var _ref$labels = _ref.labels,
    labels = _ref$labels === void 0 ? [] : _ref$labels,
    extraSideSpace = _ref.extraSideSpace,
    smartCircViewLabelRender = _ref.smartCircViewLabelRender,
    outerRadius = _ref.radius,
    editorName = _ref.editorName,
    noRedux = _ref.noRedux,
    rotationRadians = _ref.rotationRadians,
    textScalingFactor = _ref.textScalingFactor,
    labelLineIntensity = _ref.labelLineIntensity,
    _ref$labelSize = _ref.labelSize,
    labelSize = _ref$labelSize === void 0 ? 8 : _ref$labelSize,
    _ref$fontHeightMultip = _ref.fontHeightMultiplier,
    fontHeightMultiplier = _ref$fontHeightMultip === void 0 ? 2.4 : _ref$fontHeightMultip,
    circularViewWidthVsHeightRatio = _ref.circularViewWidthVsHeightRatio,
    _ref$condenseOverflow = _ref.condenseOverflowingXLabels,
    condenseOverflowingXLabels = _ref$condenseOverflow === void 0 ? true : _ref$condenseOverflow;
  if (!labels.length) {
    return {
      component: null,
      height: 15
    };
  }
  var originalOuterRadius = outerRadius;
  outerRadius += smartCircViewLabelRender ? 10 : 25;
  var radius = outerRadius;
  var outerPointRadius = outerRadius - 20;
  //we don't want the labels to grow too large on large screen devices,
  //so we start to decrease the fontWidth if the textScalingFactor is less than 1
  var fontWidth = labelSize * (textScalingFactor < 1 ? textScalingFactor : 1);
  var fontHeight = fontWidth * clamp(fontHeightMultiplier, 1.5, 3.5);
  var labelPoints = labels.map(function (label) {
    var _annotationCenterAngle = label.annotationCenterAngle,
      annotationCenterRadius = label.annotationCenterRadius;
    var annotationCenterAngle = _annotationCenterAngle + (rotationRadians || 0);
    return _extends({}, label, {
      width: getTextLength(label.text) * fontWidth,
      //three points define the label:
      innerPoint: _extends({}, polarToSpecialCartesian(annotationCenterRadius, annotationCenterAngle), {
        radius: annotationCenterRadius,
        angle: annotationCenterAngle
      }),
      truncatedInnerPoint: _extends({}, polarToSpecialCartesian(outerPointRadius - 15, annotationCenterAngle), {
        radius: outerPointRadius - 15,
        angle: annotationCenterAngle
      }),
      outerPoint: _extends({}, polarToSpecialCartesian(outerPointRadius, annotationCenterAngle), {
        radius: outerPointRadius,
        angle: annotationCenterAngle
      })
    }, polarToSpecialCartesian(radius, annotationCenterAngle), {
      radius: radius + 10,
      angle: annotationCenterAngle
    });
  }).map(function (label) {
    var _label$labelIds;
    label.labelAndSublabels = [label];
    label.labelIds = (_label$labelIds = {}, _label$labelIds[label.id] = true, _label$labelIds);
    return label;
  });
  var maxRadius = 1;
  var groupedLabels = relaxLabelAngles(labelPoints, fontHeight, outerRadius).filter(function (l) {
    return !!l;
  }).map(function (originalLabel) {
    if (smartCircViewLabelRender) {
      var newR = Math.sqrt(Math.pow(Math.abs(originalLabel.x) + Math.max(0, originalLabel.text.length * 11 - extraSideSpace / 2), 2) + Math.pow(Math.abs(originalLabel.y), 2));
      if (newR > maxRadius) maxRadius = newR;
    }
    //we need to search the labelGroup to see if any of the sub labels are highPriorityLabels
    //if they are, they should take precedence as the main group identifier
    if (originalLabel.highPriorityLabel) {
      //if the originalLabel is a highPriorityLabel, just return it
      return originalLabel;
    }
    var _highPrioritySublabel = originalLabel.labelAndSublabels.find(function (l) {
      return l.highPriorityLabel;
    });
    if (_highPrioritySublabel) {
      var highPrioritySublabel = cloneDeep(_highPrioritySublabel);
      //there is a high priority sub label, so we need to return it
      // but first we need to give it the sub-labels

      ["angle", "annotationCenterAngle", "annotationCenterRadius", "innerPoint", "labelAndSublabels", "labelIds", "outerPoint", "radius", "truncatedInnerPoint", "x", "y"].forEach(function (k) {
        highPrioritySublabel[k] = originalLabel[k];
      });
      delete originalLabel.labelAndSublabels;
      return highPrioritySublabel;
    }
    return originalLabel;
  });

  // let groupedLabels = relaxLabelAngles(
  //   labelPoints,
  //   fontHeight,
  //   outerRadius
  // ).map(label => {
  //   //in order to memoize the relaxLabelAngles function, we don't pass the full label above because it has function handlers that cause the deep equal to fail
  //   const originalLabel = {
  //     ...labels[label.id],
  //     ...label
  //   };
  //   return {
  //     ...originalLabel,
  //     labelAndSublabels: [originalLabel].concat(originalLabel.labelAndSublabels)
  //   };
  // });
  window.isLabelGroupOpen = false;
  return {
    component: /*#__PURE__*/React.createElement("g", {
      key: "veLabels",
      className: "veLabels ve-monospace-font",
      transform: "rotate(-" + rotationRadians * 180 / Math.PI + ")"
    }, /*#__PURE__*/React.createElement(DrawGroupedLabels, {
      editorName: editorName,
      noRedux: noRedux,
      groupedLabels: groupedLabels,
      circularViewWidthVsHeightRatio: circularViewWidthVsHeightRatio,
      fontWidth: fontWidth,
      fontHeight: fontHeight,
      condenseOverflowingXLabels: condenseOverflowingXLabels,
      outerRadius: outerRadius,
      labelLineIntensity: labelLineIntensity
    })),
    //we use the <use> tag to position the hovered label group at the top of the stack
    //point events: none is to fix a click bug..
    //http://stackoverflow.com/questions/24078524/svg-click-events-not-firing-bubbling-when-using-use-element
    height: smartCircViewLabelRender ? Math.min(105, maxRadius - originalOuterRadius) : 120
  };
}
export default Labels;
var DrawLabelGroup = withHover(function (_ref2) {
  var hovered = _ref2.hovered,
    className = _ref2.className,
    label = _ref2.label,
    labelAndSublabels = _ref2.labelAndSublabels,
    fontWidth = _ref2.fontWidth,
    noRedux = _ref2.noRedux,
    fontHeight = _ref2.fontHeight,
    outerRadius = _ref2.outerRadius,
    onMouseLeave = _ref2.onMouseLeave,
    onMouseOver = _ref2.onMouseOver,
    editorName = _ref2.editorName,
    circularViewWidthVsHeightRatio = _ref2.circularViewWidthVsHeightRatio,
    condenseOverflowingXLabels = _ref2.condenseOverflowingXLabels,
    hoveredId = _ref2.hoveredId,
    labelLineIntensity = _ref2.labelLineIntensity,
    multipleLabels = _ref2.multipleLabels;
  var _label$text = label.text,
    text = _label$text === void 0 ? "Unlabeled" : _label$text;
  var textLength = getTextLength(text);
  var groupLabelXStart;
  //Add the number of unshown labels
  if (label.labelAndSublabels && label.labelAndSublabels.length > 1) {
    // if (label.x > 0) {
    text = "+" + (label.labelAndSublabels.length - 1) + "," + text;
    // } else {
    //   text += ', +' + (label.labelAndSublabels.length - 1)
    // }
  }

  var labelLength = textLength * fontWidth;
  var maxLabelLength = labelAndSublabels.reduce(function (currentLength, _ref3) {
    var _ref3$text = _ref3.text,
      text = _ref3$text === void 0 ? "Unlabeled" : _ref3$text;
    var _textLength = getTextLength(text);
    if (_textLength > currentLength) {
      return _textLength;
    }
    return currentLength;
  }, 0);
  var maxLabelWidth = maxLabelLength * fontWidth;
  var labelOnLeft = label.angle > Math.PI;
  var labelXStart = label.x - (labelOnLeft ? labelLength : 0);
  if (condenseOverflowingXLabels) {
    var distancePastBoundary = Math.abs(label.x + (labelOnLeft ? -labelLength : labelLength)) - (outerRadius + 90) * Math.max(1, circularViewWidthVsHeightRatio);
    // Math.max(outerRadius (circularViewWidthVsHeightRatio / 2 + 80));
    if (distancePastBoundary > 0) {
      var numberOfCharsToChop = Math.ceil(distancePastBoundary / fontWidth) + 2;
      //   if (numberOfCharsToChop > text.length) numberOfCharsToChop = text.length
      //label overflows the boundaries!
      text = text.slice(0, -numberOfCharsToChop) + "..";
      groupLabelXStart = labelXStart + (labelOnLeft ? distancePastBoundary : -distancePastBoundary);
      labelXStart += labelOnLeft ? distancePastBoundary : 0;
    }
  }
  var dy = fontHeight;
  var textYStart = label.y + dy / 2;

  //if label xStart or label xEnd don't fit within the canvas, we need to shorten the label..

  var content;
  var labelClass = " veLabelText veCircularViewLabelText clickable " + label.color + " ";
  if ((multipleLabels || groupLabelXStart !== undefined) && hovered) {
    //HOVERED: DRAW MULTIPLE LABELS IN A RECTANGLE
    window.isLabelGroupOpen = true;
    var hoveredLabel;
    if (groupLabelXStart !== undefined) {
      labelXStart = groupLabelXStart;
    }
    labelAndSublabels.some(function (label) {
      if (label.id === hoveredId) {
        hoveredLabel = label;
        return true;
      }
      return false;
    });
    if (!hoveredLabel) {
      hoveredLabel = label;
    }
    var labelYStart = label.y;
    var labelGroupHeight = labelAndSublabels.length * dy;
    var labelGroupBottom = label.y + labelGroupHeight;
    // var numberOfLabelsToFitAbove = 0
    if (labelGroupBottom > outerRadius + 20) {
      // var diff = labelGroupBottom - (outerRadius+10)
      //calculate new label y start if necessary (the group is too long)
      labelYStart -= (label.labelAndSublabels.length - 1) * dy;
      if (labelYStart < -outerRadius) {
        //we need to make another row of labels!
      }
    }
    var line = LabelLine([hoveredLabel.innerPoint,
    // hoveredLabel.labelAndSublabels &&
    // hoveredLabel.labelAndSublabels.length > 0
    //   ? hoveredLabel.outerPoint
    //   : {},
    label], {
      style: {
        opacity: 1
      },
      strokeWidth: 2
    });
    content = [line, /*#__PURE__*/React.createElement(PutMyParentOnTop, {
      editorName: editorName,
      key: "gGroup"
    }, /*#__PURE__*/React.createElement("g", {
      className: className + " topLevelLabelGroup"
    }, /*#__PURE__*/React.createElement("rect", {
      onMouseOver: cancelFn
      // zIndex={10}
      ,
      x: labelXStart - 4,
      y: labelYStart - dy / 2,
      width: maxLabelWidth + 24,
      height: labelGroupHeight + 4,
      fill: "white",
      stroke: "black"
    }), /*#__PURE__*/React.createElement("text", {
      /* zIndex={11} */x: labelXStart,
      y: labelYStart,
      style: {
        fontSize: fontWidth * fontWidthToFontSize,
        fontStyle: label.fontStyle
      }
    }, labelAndSublabels.map(function (label, index) {
      return /*#__PURE__*/React.createElement(DrawGroupInnerLabel, {
        isSubLabel: true,
        noRedux: noRedux,
        editorName: editorName,
        logHover: true,
        key: "labelItem" + index,
        className: (label.className || "") + labelClass + " veDrawGroupInnerLabel",
        id: label.id,
        labelXStart: labelXStart,
        label: label,
        fontWidth: fontWidth,
        index: index,
        dy: dy
      });
    }))))];
  } else {
    //DRAW A SINGLE LABEL
    content = [/*#__PURE__*/React.createElement("title", {
      key: "labeltitle"
    }, label.title || label.text), /*#__PURE__*/React.createElement("text", {
      key: "text",
      x: labelXStart,
      textLength: getTextLength(text) * fontWidth,
      lengthAdjust: "spacing",
      className: labelClass + label.className + (hovered ? " veAnnotationHovered" : ""),
      y: textYStart,
      style: {
        fontSize: fontWidth * fontWidthToFontSize,
        fontStyle: label.fontStyle,
        fill: label.color || "black"
        // stroke: label.color ? label.color : "black"
      }
    }, text), LabelLine([label.innerPoint,
    // hovered || label.annotationType === "part" //because parts live on the outside of the sequence, we don't need to show the truncated point, we can just point to them directly
    //   ? label.innerPoint
    //   : label.truncatedInnerPoint,
    label.outerPoint, label], hovered ? {
      style: {
        opacity: 1
      },
      strokeWidth: 2
    } : {
      style: {
        opacity: labelLineIntensity
      }
    })];
  }
  return /*#__PURE__*/React.createElement("g", {
    onMouseLeave: onMouseLeave,
    onMouseOver: onMouseOver,
    onClick: label.onClick,
    onDoubleClick: label.onDoubleClick || noop,
    onContextMenu: label.onContextMenu || noop
  }, content);
});
function LabelLine(pointArray, options) {
  var points = "";
  pointArray.forEach(function (_ref4) {
    var x = _ref4.x,
      y = _ref4.y;
    if (!x && x !== 0) return;
    points += x + "," + y + " ";
  });
  return /*#__PURE__*/React.createElement(React.Fragment, {
    key: "labelLine"
  }, /*#__PURE__*/React.createElement("polyline", _extends({
    key: "polyline-long",
    points: points,
    stroke: "black",
    fill: "none",
    strokeWidth: 1,
    className: "veLabelLine"
  }, options)));
}
var DrawGroupInnerLabel = withHover(function (_ref5) {
  var className = _ref5.className,
    labelXStart = _ref5.labelXStart,
    label = _ref5.label,
    fontWidth = _ref5.fontWidth,
    onMouseOver = _ref5.onMouseOver,
    index = _ref5.index,
    dy = _ref5.dy;
  return /*#__PURE__*/React.createElement("tspan", {
    x: labelXStart,
    textLength: getTextLength(label.text) * fontWidth,
    lengthAdjust: "spacing",
    onClick: label.onClick,
    onDoubleClick: function onDoubleClick(e) {
      e.stopPropagation();
      label.onDoubleClick && label.onDoubleClick(e);
    },
    onContextMenu: label.onContextMenu,
    dy: index === 0 ? dy / 2 : dy,
    style: {
      fill: label.color ? label.color : "black",
      fontStyle: label.fontStyle
    },
    onMouseOver: onMouseOver,
    className: className
  }, /*#__PURE__*/React.createElement("title", null, label.title), label.text);
});
function noop() {}
var DrawGroupedLabels = function DrawGroupedLabelsInner(_ref6) {
  var groupedLabels = _ref6.groupedLabels,
    circularViewWidthVsHeightRatio = _ref6.circularViewWidthVsHeightRatio,
    fontWidth = _ref6.fontWidth,
    noRedux = _ref6.noRedux,
    fontHeight = _ref6.fontHeight,
    condenseOverflowingXLabels = _ref6.condenseOverflowingXLabels,
    outerRadius = _ref6.outerRadius,
    editorName = _ref6.editorName,
    labelLineIntensity = _ref6.labelLineIntensity;
  return groupedLabels.map(function (label, i) {
    var labelAndSublabels = label.labelAndSublabels,
      labelIds = label.labelIds;
    var multipleLabels = labelAndSublabels.length > 1;
    return /*#__PURE__*/React.createElement(DrawLabelGroup, {
      key: i,
      id: labelIds,
      label: label,
      noRedux: noRedux,
      passHoveredId: true,
      //needed to get the hoveredId
      isLabelGroup: true,
      className: "DrawLabelGroup",
      multipleLabels: multipleLabels,
      labelAndSublabels: labelAndSublabels,
      labelIds: labelIds,
      circularViewWidthVsHeightRatio: circularViewWidthVsHeightRatio,
      fontWidth: fontWidth,
      editorName: editorName,
      fontHeight: fontHeight,
      condenseOverflowingXLabels: condenseOverflowingXLabels,
      outerRadius: outerRadius,
      labelLineIntensity: labelLineIntensity
    });
  });
};
function cancelFn(e) {
  e.stopPropagation();
}
var PutMyParentOnTop = /*#__PURE__*/function (_React$Component) {
  _inheritsLoose(PutMyParentOnTop, _React$Component);
  function PutMyParentOnTop() {
    return _React$Component.apply(this, arguments) || this;
  }
  var _proto = PutMyParentOnTop.prototype;
  _proto.componentDidMount = function componentDidMount() {
    var editorName = this.props.editorName;
    //we use this component to re-order the svg groupedLabels because z-index won't work in svgs
    try {
      var el = document.querySelector(".veEditor." + editorName + " .topLevelLabelGroup");
      var parent = el.parentElement.parentElement;
      var i = Array.prototype.indexOf.call(parent.children, el.parentElement);
      parent.insertBefore(parent.children[i], null); //insert at the end of the list..
    } catch (error) {
      console.warn("OVE-975239 - hit an error trying to re-order labels:", error);
    }
  };
  _proto.render = function render() {
    return this.props.children;
  };
  return PutMyParentOnTop;
}(React.Component);