var _excluded = ["sequenceData", "alignmentData", "hideName", "editorClicked", "width", "className", "tickSpacing", "scrollDataPassed", "caretPosition", "backgroundRightClicked", "RowItemProps", "marginWidth", "height", "isInAlignment", "withZoomLinearView", "editorName", "smallSlider", "paddingBottom", "linearViewCharWidth", "annotationVisibilityOverrides", "isProtein", "noWarnings"];
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
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); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
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 _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
import { debounce, startCase } from "lodash";
import draggableClassnames from "../constants/draggableClassnames";
import prepareRowData from "../utils/prepareRowData";
import React from "react";
import Draggable from "react-draggable";
import RowItem from "../RowItem";
import withEditorInteractions from "../withEditorInteractions";
import { withEditorPropsNoRedux } from "../withEditorProps";
import "./style.css";
import { getClientX, getEmptyText, getParedDownWarning, pareDownAnnotations } from "../utils/editorUtils";
import useAnnotationLimits from "../utils/useAnnotationLimits";
import { SequenceName } from "./SequenceName";
import classNames from "classnames";
import { massageTickSpacing } from "../utils/massageTickSpacing";
import PinchHelper from "../helperComponents/PinchHelper/PinchHelper";
import { updateLabelsForInViewFeatures } from "../utils/updateLabelsForInViewFeatures";
import { VeTopRightContainer } from "../CircularView/VeTopRightContainer";
import { ZoomLinearView } from "./ZoomLinearView";
import { editorDragged, editorDragStarted, editorDragStopped } from "../withEditorInteractions/clickAndDragUtils";
import { store } from "@risingstack/react-easy-state";
var defaultMarginWidth = 10;
function noop() {}
var _LinearView = /*#__PURE__*/function (_React$Component) {
  _inheritsLoose(_LinearView, _React$Component);
  function _LinearView() {
    var _this;
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }
    _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
    _defineProperty(_assertThisInitialized(_this), "state", {});
    _defineProperty(_assertThisInitialized(_this), "bindOutsideChangeHelper", {});
    _defineProperty(_assertThisInitialized(_this), "getMaxLength", function () {
      var _this$props = _this.props,
        _this$props$sequenceD = _this$props.sequenceData,
        sequenceData = _this$props$sequenceD === void 0 ? {
          sequence: ""
        } : _this$props$sequenceD,
        alignmentData = _this$props.alignmentData;
      var data = alignmentData || sequenceData;
      return data.noSequence ? data.size : data.sequence.length;
    });
    _defineProperty(_assertThisInitialized(_this), "getRowData", function () {
      var _this$props2 = _this.props,
        limits = _this$props2.limits,
        _this$props2$sequence = _this$props2.sequenceData,
        sequenceData = _this$props2$sequence === void 0 ? {
          sequence: ""
        } : _this$props2$sequence,
        maxAnnotationsToDisplay = _this$props2.maxAnnotationsToDisplay;
      // if (!isEqual(sequenceData, this.oldSeqData)) {
      _this.paredDownMessages = [];
      var paredDownSeqData = ["parts", "features", "cutsites"].reduce(function (acc, type) {
        var nameUpper = startCase(type);
        var maxToShow = (maxAnnotationsToDisplay ? maxAnnotationsToDisplay[type] : limits[type]) || 50;
        var _pareDownAnnotations = pareDownAnnotations(sequenceData["filtered" + nameUpper] || sequenceData[type] || {}, maxToShow),
          annotations = _pareDownAnnotations[0],
          paredDown = _pareDownAnnotations[1];
        if (paredDown) {
          _this.paredDownMessages.push(getParedDownWarning({
            nameUpper: nameUpper,
            isAdjustable: !maxAnnotationsToDisplay,
            maxToShow: maxToShow
          }));
        }
        acc[type] = annotations;
        return acc;
      }, {});
      _this.rowData = prepareRowData(_extends({}, sequenceData, paredDownSeqData), sequenceData.sequence ? sequenceData.sequence.length : 0);
      _this.oldSeqData = sequenceData;
      // }
      return _this.rowData;
    });
    _defineProperty(_assertThisInitialized(_this), "updateLabelsForInViewFeaturesDebounced", debounce(function () {
      updateLabelsForInViewFeatures();
    }, 20));
    _defineProperty(_assertThisInitialized(_this), "easyStore", store({
      percentScrolled: 0,
      viewportWidth: 400
    }));
    return _this;
  }
  var _proto = _LinearView.prototype;
  _proto.getNearestCursorPositionToMouseEvent = function getNearestCursorPositionToMouseEvent(rowData, event, callback) {
    //loop through all the rendered rows to see if the click event lands in one of them
    var nearestCaretPos = 0;
    var rowDomNode = this.linearView;
    rowDomNode = rowDomNode.querySelector(".veRowItem");
    var boundingRowRect = rowDomNode.getBoundingClientRect();
    var maxEnd = this.getMaxLength();
    if (getClientX(event) - boundingRowRect.left < 0) {
      nearestCaretPos = 0;
    } else {
      var clickXPositionRelativeToRowContainer = getClientX(event) - boundingRowRect.left;
      var numberOfBPsInFromRowStart = Math.floor((clickXPositionRelativeToRowContainer + this.charWidth / 2) / this.charWidth);
      nearestCaretPos = numberOfBPsInFromRowStart + 0;
      if (nearestCaretPos > maxEnd + 1) {
        nearestCaretPos = maxEnd + 1;
      }
    }
    if (this.props.sequenceData && this.props.sequenceData.isProtein) {
      nearestCaretPos = Math.round(nearestCaretPos / 3) * 3;
    }
    if (maxEnd === 0) nearestCaretPos = 0;
    var _this$props3 = this.props,
      updateSelectionOrCaret = _this$props3.updateSelectionOrCaret,
      caretPosition = _this$props3.caretPosition,
      selectionLayer = _this$props3.selectionLayer,
      caretPositionUpdate = _this$props3.caretPositionUpdate,
      selectionLayerUpdate = _this$props3.selectionLayerUpdate;
    var callbackVals = {
      updateSelectionOrCaret: updateSelectionOrCaret,
      caretPosition: caretPosition,
      selectionLayer: selectionLayer,
      caretPositionUpdate: caretPositionUpdate,
      selectionLayerUpdate: selectionLayerUpdate,
      sequenceLength: maxEnd,
      doNotWrapOrigin: !(this.props.sequenceData && this.props.sequenceData.circular),
      event: event,
      shiftHeld: event.shiftKey,
      nearestCaretPos: nearestCaretPos,
      // caretGrabbed: event.target.className === "cursor",
      selectionStartGrabbed: event.target.classList.contains(draggableClassnames.selectionStart),
      selectionEndGrabbed: event.target.classList.contains(draggableClassnames.selectionEnd)
    };
    callback(callbackVals);
  };
  _proto.render = function render() {
    var _this2 = this;
    var _this$props4 = this.props,
      _this$props4$sequence = _this$props4.sequenceData,
      sequenceData = _this$props4$sequence === void 0 ? {
        sequence: ""
      } : _this$props4$sequence,
      alignmentData = _this$props4.alignmentData,
      _this$props4$hideName = _this$props4.hideName,
      hideName = _this$props4$hideName === void 0 ? false : _this$props4$hideName,
      _this$props4$editorCl = _this$props4.editorClicked,
      editorClicked = _this$props4$editorCl === void 0 ? noop : _this$props4$editorCl,
      _this$props4$width = _this$props4.width,
      width = _this$props4$width === void 0 ? 400 : _this$props4$width,
      className = _this$props4.className,
      tickSpacing = _this$props4.tickSpacing,
      scrollDataPassed = _this$props4.scrollDataPassed,
      caretPosition = _this$props4.caretPosition,
      _this$props4$backgrou = _this$props4.backgroundRightClicked,
      backgroundRightClicked = _this$props4$backgrou === void 0 ? noop : _this$props4$backgrou,
      _this$props4$RowItemP = _this$props4.RowItemProps,
      RowItemProps = _this$props4$RowItemP === void 0 ? {} : _this$props4$RowItemP,
      _this$props4$marginWi = _this$props4.marginWidth,
      marginWidth = _this$props4$marginWi === void 0 ? defaultMarginWidth : _this$props4$marginWi,
      height = _this$props4.height,
      isInAlignment = _this$props4.isInAlignment,
      _this$props4$withZoom = _this$props4.withZoomLinearView,
      withZoomLinearView = _this$props4$withZoom === void 0 ? false : _this$props4$withZoom,
      editorName = _this$props4.editorName,
      smallSlider = _this$props4.smallSlider,
      paddingBottom = _this$props4.paddingBottom,
      linearViewCharWidth = _this$props4.linearViewCharWidth,
      annotationVisibilityOverrides = _this$props4.annotationVisibilityOverrides,
      isProtein = _this$props4.isProtein,
      noWarnings = _this$props4.noWarnings,
      rest = _objectWithoutPropertiesLoose(_this$props4, _excluded);
    var bpsPerRow = this.getMaxLength();
    var innerWidth = Math.max(width - marginWidth - 20, 0);
    if (isNaN(innerWidth)) {
      innerWidth = 0;
    }
    var initialCharWidth = Math.min(innerWidth / bpsPerRow, 20);
    this.charWidth = this.state.charWidthInLinearView || linearViewCharWidth || initialCharWidth;
    var isLinViewZoomed = this.charWidth !== initialCharWidth;
    var sequenceName = hideName ? "" : sequenceData.name || "";
    var rowData = this.getRowData();
    var linearZoomEnabled = bpsPerRow >= 50 && withZoomLinearView;
    var minCharWidth = initialCharWidth;
    var PinchHelperToUse = linearZoomEnabled ? PinchHelper : React.Fragment;
    var pinchHandler = {
      onPinch: function onPinch(_ref) {
        var _ref$delta = _ref.delta,
          d = _ref$delta[0];
        if (d === 0) return;
        _this2.bindOutsideChangeHelper.triggerChange(function (_ref2) {
          var value = _ref2.value,
            changeValue = _ref2.changeValue;
          // changeValue(d);
          if (d > 0) {
            if (value > 8) {
              changeValue(value + 0.4);
            } else {
              changeValue(value + 0.2);
            }
          } else if (d < 0) {
            if (value > 8) {
              changeValue(value - 0.4);
            } else {
              changeValue(value - 0.2);
            }
          }
        });
        updateLabelsForInViewFeatures();
      }
    };
    return /*#__PURE__*/React.createElement(Draggable, {
      enableUserSelectHack: false //needed to prevent the input bubble from losing focus post user drag
      ,
      bounds: {
        top: 0,
        left: 0,
        right: 0,
        bottom: 0
      },
      onDrag: function onDrag(event) {
        _this2.getNearestCursorPositionToMouseEvent(rowData, event, _this2.props.editorDragged || editorDragged);
      },
      onStart: function onStart(event) {
        _this2.getNearestCursorPositionToMouseEvent(rowData, event, _this2.props.editorDragStarted || editorDragStarted);
      },
      onStop: this.props.editorDragStopped || editorDragStopped
    }, /*#__PURE__*/React.createElement("div", {
      ref: function ref(_ref3) {
        return _this2.linearView = _ref3;
      },
      className: classNames("veLinearView", className, {
        isLinViewZoomed: isLinViewZoomed
      }),
      style: _extends({
        width: width
      }, height && {
        height: height
      }, {
        paddingLeft: marginWidth / 2
      }, paddingBottom && {
        paddingBottom: paddingBottom
      }),
      onContextMenu: function onContextMenu(event) {
        _this2.getNearestCursorPositionToMouseEvent(rowData, event, backgroundRightClicked);
      },
      onClick: function onClick(event) {
        _this2.getNearestCursorPositionToMouseEvent(rowData, event, editorClicked);
      }
    }, linearZoomEnabled &&
    /*#__PURE__*/
    //so this for conditonal rendering
    React.createElement(ZoomLinearView, {
      charWidth: this.charWidth,
      bindOutsideChangeHelper: this.bindOutsideChangeHelper,
      minCharWidth: minCharWidth,
      smallSlider: smallSlider,
      editorName: editorName,
      setCharWidth: function setCharWidth(v) {
        _this2.setState({
          charWidthInLinearView: v === initialCharWidth ? undefined : v
        });
      },
      afterOnChange: function afterOnChange() {
        updateLabelsForInViewFeatures();
      }
    }), !hideName && /*#__PURE__*/React.createElement(SequenceName, {
      isProtein: isProtein,
      sequenceName: sequenceName,
      sequenceLength: sequenceData.sequence ? sequenceData.sequence.length : 0
    }), !noWarnings && /*#__PURE__*/React.createElement(VeTopRightContainer, null, this.paredDownMessages), /*#__PURE__*/React.createElement(PinchHelperToUse, linearZoomEnabled && pinchHandler, /*#__PURE__*/React.createElement(RowItem, _extends({}, _extends({}, rest, {
      editorName: editorName,
      onScroll: function onScroll() {
        _this2.easyStore.viewportWidth = width;
        var row = _this2.linearView.querySelector(".veRowItemWrapper");
        var scrollPercentage = row.scrollLeft / (row.scrollWidth - row.clientWidth);
        _this2.easyStore.percentScrolled = scrollPercentage;
        updateLabelsForInViewFeatures();
      },
      rowContainerStyle: _extends({
        height: height - 36,
        width: innerWidth + 26,
        paddingRight: marginWidth / 2
      }, isLinViewZoomed && !isInAlignment && {
        paddingBottom: 15
      }),
      charWidth: this.charWidth,
      scrollData: scrollDataPassed || (isLinViewZoomed ? this.easyStore : undefined),
      caretPosition: caretPosition,
      isProtein: sequenceData.isProtein,
      alignmentData: alignmentData,
      sequenceLength: this.getMaxLength(),
      bpsPerRow: bpsPerRow,
      fullSequence: sequenceData.sequence,
      emptyText: getEmptyText({
        sequenceData: sequenceData,
        caretPosition: caretPosition
      }),
      tickSpacing: tickSpacing || (isLinViewZoomed ? massageTickSpacing(Math.ceil(120 / this.charWidth)) : Math.floor(this.getMaxLength() / (sequenceData.isProtein ? 9 : 10))),
      annotationVisibility: _extends({}, rest.annotationVisibility, (!isLinViewZoomed || this.charWidth < 5) && {
        translations: false,
        primaryProteinSequence: false,
        reverseSequence: false,
        sequence: false,
        cutsitesInSequence: false
      }, annotationVisibilityOverrides)
    }, RowItemProps), {
      row: rowData[0],
      isLinearView: true
    })))));
  };
  return _LinearView;
}(React.Component);
var WithAnnotationLimitsHoc = function WithAnnotationLimitsHoc(Component) {
  return function (props) {
    // eslint-disable-next-line react-hooks/rules-of-hooks
    var _useAnnotationLimits = useAnnotationLimits(),
      _useAnnotationLimits$ = _useAnnotationLimits[0],
      limits = _useAnnotationLimits$ === void 0 ? {} : _useAnnotationLimits$;
    return /*#__PURE__*/React.createElement(Component, _extends({
      limits: limits
    }, props));
  };
};
export var LinearView = WithAnnotationLimitsHoc(_LinearView);
export var NonReduxEnhancedLinearView = withEditorPropsNoRedux(LinearView);
export default withEditorInteractions(LinearView);
export var scrollToCaret = function scrollToCaret() {
  var el = window.document.querySelector(".veLinearView .veRowViewCaret");
  if (!el) return;
  el.scrollIntoView({
    inline: "center",
    block: "nearest"
  });
};