var __extends = this && this.__extends || function () {
  var _extendStatics = function extendStatics(d, b) {
    _extendStatics = Object.setPrototypeOf || {
      __proto__: []
    } instanceof Array && function (d, b) {
      d.__proto__ = b;
    } || function (d, b) {
      for (var p in b) {
        if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
      }
    };

    return _extendStatics(d, b);
  };

  return function (d, b) {
    if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");

    _extendStatics(d, b);

    function __() {
      this.constructor = d;
    }

    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  };
}();

var __assign = this && this.__assign || function () {
  __assign = Object.assign || function (t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
      s = arguments[i];

      for (var p in s) {
        if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
      }
    }

    return t;
  };

  return __assign.apply(this, arguments);
};

import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import classNames from 'classnames';
import memoizeOne from 'memoize-one';
import addEventListener from 'rc-util/lib/Dom/addEventListener';
import Affix from "../affix";
import { scrollTo, getScroll } from "./utils";
import AnchorContext from "./context";
import "./style/anchor.css";
export var ConfigContext = /*#__PURE__*/React.createContext({
  getPrefixCls: function getPrefixCls() {
    return 'dmc-anchor';
  }
});

function getDefaultContainer() {
  return window;
}

function getOffsetTop(element, container) {
  if (!element.getClientRects().length) {
    return 0;
  }

  var rect = element.getBoundingClientRect();

  if (rect.width || rect.height) {
    if (container === window) {
      container = element.ownerDocument.documentElement;
      return rect.top - container.clientTop;
    }

    return rect.top - container.getBoundingClientRect().top;
  }

  return rect.top;
}

var sharpMatcherRegx = /#([\S ]+)$/;

var Anchor =
/** @class */
function (_super) {
  __extends(Anchor, _super);

  function Anchor() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.state = {
      activeLink: null
    };
    _this.wrapperRef = /*#__PURE__*/React.createRef();
    _this.links = []; // Context

    _this.registerLink = function (link) {
      if (!_this.links.includes(link)) {
        _this.links.push(link);
      }
    };

    _this.unregisterLink = function (link) {
      var index = _this.links.indexOf(link);

      if (index !== -1) {
        _this.links.splice(index, 1);
      }
    };

    _this.getContainer = function () {
      var getTargetContainer = _this.context.getTargetContainer;
      var getContainer = _this.props.getContainer;
      var getFunc = getContainer || getTargetContainer || getDefaultContainer;
      return getFunc();
    };

    _this.handleScrollTo = function (link) {
      var _a = _this.props,
          offsetTop = _a.offsetTop,
          targetOffset = _a.targetOffset;

      _this.setCurrentActiveLink(link);

      var container = _this.getContainer();

      var scrollTop = getScroll(container, true);
      var sharpLinkMatch = sharpMatcherRegx.exec(link);

      if (!sharpLinkMatch) {
        return;
      }

      var targetElement = document.getElementById(sharpLinkMatch[1]);

      if (!targetElement) {
        return;
      }

      var eleOffsetTop = getOffsetTop(targetElement, container);
      var y = scrollTop + eleOffsetTop;
      y -= targetOffset !== undefined ? targetOffset : offsetTop || 0;
      _this.animating = true;
      scrollTo(y, {
        callback: function callback() {
          _this.animating = false;
        },
        getContainer: _this.getContainer
      });
    };

    _this.saveInkNode = function (node) {
      _this.inkNode = node;
    };

    _this.setCurrentActiveLink = function (link) {
      var activeLink = _this.state.activeLink;
      var _a = _this.props,
          onChange = _a.onChange,
          getCurrentAnchor = _a.getCurrentAnchor;

      if (activeLink === link) {
        return;
      }

      _this.setState({
        activeLink: typeof getCurrentAnchor === 'function' ? getCurrentAnchor() : link
      });

      onChange === null || onChange === void 0 ? void 0 : onChange(link);
    };

    _this.handleScroll = function () {
      if (_this.animating) {
        return;
      }

      var _a = _this.props,
          offsetTop = _a.offsetTop,
          bounds = _a.bounds,
          targetOffset = _a.targetOffset;

      var currentActiveLink = _this.getCurrentAnchor(targetOffset !== undefined ? targetOffset : offsetTop || 0, bounds);

      _this.setCurrentActiveLink(currentActiveLink);
    };

    _this.updateInk = function () {
      var _a = _this,
          prefixCls = _a.prefixCls,
          wrapperRef = _a.wrapperRef;
      var anchorNode = wrapperRef.current;
      var linkNode = anchorNode === null || anchorNode === void 0 ? void 0 : anchorNode.getElementsByClassName(prefixCls + "-link-title-active")[0];

      if (linkNode) {
        _this.inkNode.style.top = linkNode.offsetTop + linkNode.clientHeight / 2 - 8 + "px";
      }
    };

    _this.getMemoizedContextValue = memoizeOne(function (link, onClickFn) {
      return {
        registerLink: _this.registerLink,
        unregisterLink: _this.unregisterLink,
        scrollTo: _this.handleScrollTo,
        activeLink: link,
        onClick: onClickFn
      };
    });
    return _this;
  }

  Anchor.prototype.componentDidMount = function () {
    this.scrollContainer = this.getContainer();
    this.scrollEvent = addEventListener(this.scrollContainer, 'scroll', this.handleScroll);
    this.handleScroll();
  };

  Anchor.prototype.componentDidUpdate = function () {
    if (this.scrollEvent) {
      var currentContainer = this.getContainer();

      if (this.scrollContainer !== currentContainer) {
        this.scrollContainer = currentContainer;
        this.scrollEvent.remove();
        this.scrollEvent = addEventListener(this.scrollContainer, 'scroll', this.handleScroll);
        this.handleScroll();
      }
    }

    this.updateInk();
  };

  Anchor.prototype.componentWillUnmount = function () {
    if (this.scrollEvent) {
      this.scrollEvent.remove();
    }
  };

  Anchor.prototype.getCurrentAnchor = function (offsetTop, bounds) {
    if (offsetTop === void 0) {
      offsetTop = 0;
    }

    if (bounds === void 0) {
      bounds = 5;
    }

    var linkSections = [];
    var container = this.getContainer();
    this.links.forEach(function (link) {
      var sharpLinkMatch = sharpMatcherRegx.exec(link.toString());

      if (!sharpLinkMatch) {
        return;
      }

      var target = document.getElementById(sharpLinkMatch[1]);

      if (target) {
        var top_1 = getOffsetTop(target, container);

        if (top_1 < offsetTop + bounds) {
          linkSections.push({
            link: link,
            top: top_1
          });
        }
      }
    });

    if (linkSections.length) {
      var maxSection = linkSections.reduce(function (prev, curr) {
        return curr.top > prev.top ? curr : prev;
      });
      return maxSection.link;
    }

    return '';
  };

  Anchor.prototype.render = function () {
    var _a, _b;

    var _c = this.context,
        getPrefixCls = _c.getPrefixCls,
        direction = _c.direction;
    var _d = this.props,
        customizePrefixCls = _d.prefixCls,
        _e = _d.className,
        className = _e === void 0 ? '' : _e,
        style = _d.style,
        offsetTop = _d.offsetTop,
        affix = _d.affix,
        showInkInFixed = _d.showInkInFixed,
        children = _d.children,
        onClick = _d.onClick;
    var activeLink = this.state.activeLink;
    var prefixCls = getPrefixCls('anchor', customizePrefixCls);
    this.prefixCls = prefixCls;
    var inkClass = classNames(prefixCls + "-ink-ball", {
      visible: activeLink
    });
    var wrapperClass = classNames(prefixCls + "-wrapper", (_a = {}, _a[prefixCls + "-rtl"] = direction === 'rtl', _a), className);
    var anchorClass = classNames(prefixCls, (_b = {}, _b[prefixCls + "-fixed"] = !affix && !showInkInFixed, _b));

    var wrapperStyle = __assign({
      maxHeight: offsetTop ? "calc(100vh - " + offsetTop + "px)" : '100vh'
    }, style);

    var anchorContent = _jsx("div", __assign({
      ref: this.wrapperRef,
      className: wrapperClass,
      style: wrapperStyle
    }, {
      children: _jsxs("div", __assign({
        className: anchorClass
      }, {
        children: [_jsx("div", __assign({
          className: prefixCls + "-ink"
        }, {
          children: _jsx("span", {
            className: inkClass,
            ref: this.saveInkNode
          }, void 0)
        }), void 0), children]
      }), void 0)
    }), void 0);

    var contextValue = this.getMemoizedContextValue(activeLink, onClick);
    return _jsx(AnchorContext.Provider, __assign({
      value: contextValue
    }, {
      children: !affix ? anchorContent : _jsx(Affix, __assign({
        offsetTop: offsetTop,
        target: this.getContainer
      }, {
        children: anchorContent
      }), void 0)
    }), void 0);
  };

  Anchor.defaultProps = {
    affix: true,
    showInkInFixed: false
  };
  Anchor.contextType = ConfigContext;
  return Anchor;
}(React.Component);

export default Anchor;
var AnchorMemo = /*#__PURE__*/React.memo(Anchor); // AnchorMemo.displayName = 'AffixMemo';

export { AnchorMemo };

