var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (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);
};
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import React from 'react';
import debounce from 'lodash.debounce';
import { isInstanceOf } from '../../lib/isInstanceOf.js';
import * as LayoutEvents from '../../lib/LayoutEvents.js';
import { CommonWrapper } from '../../internal/CommonWrapper/index.js';
import { rootNode } from '../../lib/rootNode/index.js';
import { getDOMRect } from '../../lib/dom/getDOMRect.js';
import { createPropsGetter } from '../../lib/createPropsGetter.js';
import { isTestEnv } from '../../lib/currentEnvironment.js';
import { callChildRef } from '../../lib/callChildRef/callChildRef.js';
import { withRenderEnvironment } from '../../lib/renderEnvironment/index.js';
import { getStyles, globalClasses } from './ScrollContainer.styles.js';
import { scrollSizeParametersNames } from './ScrollContainer.constants.js';
import { convertScrollbarXScrollState, convertScrollbarYScrollState, getScrollYOffset, } from './ScrollContainer.helpers.js';
import { ScrollBar } from './ScrollBar.js';
export var ScrollContainerDataTids = {
    root: 'ScrollContainer__root',
    inner: 'ScrollContainer__inner',
};
/**
 * `ScrollContainer` используется для создания контейнера с кастомными полосами прокрутки, который обеспечивает прокрутку содержимого по горизонтали или вертикали.
 */
var ScrollContainer = /** @class */ (function (_super) {
    __extends(ScrollContainer, _super);
    function ScrollContainer() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.getProps = createPropsGetter(ScrollContainer_1.defaultProps);
        _this.initialIsScrollBarVisible = _this.getProps().showScrollBar === 'always';
        _this.state = {
            isScrollBarXVisible: _this.initialIsScrollBarVisible,
            isScrollBarYVisible: _this.initialIsScrollBarVisible,
            isHovered: false,
        };
        _this.renderScrollbar = function (axis) {
            var _a = _this.getProps(), offsetY = _a.offsetY, offsetX = _a.offsetX, invert = _a.invert, disableAnimations = _a.disableAnimations;
            var isAxisX = axis === 'x';
            var refScrollBar = isAxisX ? _this.refScrollBarX : _this.refScrollBarY;
            var offset = isAxisX ? offsetX : offsetY;
            var isVisible = isAxisX ? _this.state.isScrollBarXVisible : _this.state.isScrollBarYVisible;
            return (React.createElement(ScrollBar, { axis: axis, ref: refScrollBar, invert: invert, onScroll: _this.handleScroll, offset: offset, disableAnimations: disableAnimations, isVisible: isVisible }));
        };
        _this.handleScrollStateChange = function (scrollState, axis) {
            var _a, _b, _c, _d;
            if (!_this.scrollY || !_this.scrollX) {
                return;
            }
            if (axis === 'x') {
                var scrollXState = convertScrollbarXScrollState(scrollState);
                (_b = (_a = _this.props).onScrollStateChangeX) === null || _b === void 0 ? void 0 : _b.call(_a, scrollXState);
                return;
            }
            var scrollYState = convertScrollbarYScrollState(scrollState);
            (_d = (_c = _this.props).onScrollStateChangeY) === null || _d === void 0 ? void 0 : _d.call(_c, scrollYState);
        };
        _this.handleScroll = function (axis, scrollState, prevScrollState) {
            if (scrollState !== prevScrollState) {
                _this.handleScrollStateChange(scrollState, axis);
            }
            var showScrollBar = _this.getProps().showScrollBar;
            showScrollBar === 'scroll' && _this.showScrollBarOnMouseWheel(axis);
        };
        _this.refScrollBarY = function (scrollbar) {
            _this.scrollY = scrollbar;
        };
        _this.refScrollBarX = function (scrollbar) {
            _this.scrollX = scrollbar;
        };
        _this.refInner = function (element) {
            if (!_this.inner && element && _this.getProps().preventWindowScroll) {
                element.addEventListener('wheel', _this.handleInnerScrollWheel, { passive: false });
            }
            if (_this.inner && !element) {
                _this.inner.removeEventListener('wheel', _this.handleInnerScrollWheel);
            }
            _this.inner = element;
            if (_this.props.scrollRef) {
                callChildRef(_this.props.scrollRef, element);
            }
        };
        _this.handleNativeScroll = function (event) {
            var _a, _b, _c, _d;
            (_a = _this.scrollY) === null || _a === void 0 ? void 0 : _a.reflow();
            (_b = _this.scrollX) === null || _b === void 0 ? void 0 : _b.reflow();
            (_d = (_c = _this.props).onScroll) === null || _d === void 0 ? void 0 : _d.call(_c, event);
            if (_this.getProps().preventWindowScroll) {
                event.preventDefault();
                return;
            }
            LayoutEvents.emit();
        };
        _this.showScrollBarOnMouseWheel = function (axis) {
            var isScrollBarVisible = axis === 'x' ? _this.state.isScrollBarXVisible : _this.state.isScrollBarYVisible;
            if (!isScrollBarVisible) {
                axis === 'x' ? _this.setState({ isScrollBarXVisible: true }) : _this.setState({ isScrollBarYVisible: true });
            }
            _this.hideScrollBar(axis);
        };
        _this.hideScrollBar = debounce(function (axis) {
            var _a, _b;
            if (_this.state.isHovered) {
                return;
            }
            var isScrollBarXHovered = (_a = _this.scrollX) === null || _a === void 0 ? void 0 : _a.getHover();
            var isScrollBarYHovered = (_b = _this.scrollY) === null || _b === void 0 ? void 0 : _b.getHover();
            if (axis === 'both') {
                !isScrollBarXHovered && !isScrollBarYHovered
                    ? _this.setState({ isScrollBarXVisible: false, isScrollBarYVisible: false })
                    : _this.hideScrollBar('both');
            }
            else if (axis === 'x') {
                !isScrollBarXHovered ? _this.setState({ isScrollBarXVisible: false }) : _this.hideScrollBar('x');
            }
            else {
                !isScrollBarYHovered ? _this.setState({ isScrollBarYVisible: false }) : _this.hideScrollBar('y');
            }
        }, _this.getProps().hideScrollBarDelay);
        _this.handleInnerScrollWheel = function (event) {
            if (!_this.inner || !isInstanceOf(event, _this.globalObject.WheelEvent)) {
                return;
            }
            var axis = event.shiftKey ? 'x' : 'y';
            if (_this.hasScrollBar(axis)) {
                var _a = scrollSizeParametersNames[axis], pos = _a.pos, size = _a.size, offset = _a.offset;
                if (event.deltaY > 0 && _this.inner[size] <= _this.inner[pos] + _this.inner[offset]) {
                    event.preventDefault();
                    return false;
                }
                if (event.deltaY < 0 && _this.inner[pos] <= 0) {
                    event.preventDefault();
                    return false;
                }
            }
        };
        _this.handleMouseMove = function (event) {
            var _a, _b;
            var right = getDOMRect(event.currentTarget).right - event.pageX;
            var bottom = getDOMRect(event.currentTarget).bottom - event.pageY;
            (_a = _this.scrollY) === null || _a === void 0 ? void 0 : _a.setHover(right <= 12);
            (_b = _this.scrollX) === null || _b === void 0 ? void 0 : _b.setHover(right >= 12 && bottom <= 12);
            _this.getProps().showScrollBar === 'hover' &&
                !_this.state.isHovered &&
                _this.setState({ isScrollBarXVisible: true, isScrollBarYVisible: true, isHovered: true });
        };
        _this.handleMouseLeave = function () {
            var _a, _b;
            (_a = _this.scrollY) === null || _a === void 0 ? void 0 : _a.setHover(false);
            (_b = _this.scrollX) === null || _b === void 0 ? void 0 : _b.setHover(false);
            if (_this.getProps().showScrollBar === 'hover') {
                _this.setState({ isHovered: false });
                _this.hideScrollBar('both');
            }
        };
        _this.updateInnerElement = function () {
            var _a, _b;
            (_a = _this.scrollX) === null || _a === void 0 ? void 0 : _a.setInnerElement(_this.inner);
            (_b = _this.scrollY) === null || _b === void 0 ? void 0 : _b.setInnerElement(_this.inner);
        };
        return _this;
    }
    ScrollContainer_1 = ScrollContainer;
    ScrollContainer.prototype.componentDidMount = function () {
        this.updateInnerElement();
    };
    ScrollContainer.prototype.componentDidUpdate = function (prevProps) {
        var preventWindowScroll = this.getProps().preventWindowScroll;
        if (this.inner) {
            if (prevProps.preventWindowScroll && !preventWindowScroll) {
                this.inner.removeEventListener('wheel', this.handleInnerScrollWheel);
            }
            if (!prevProps.preventWindowScroll && preventWindowScroll) {
                this.inner.addEventListener('wheel', this.handleInnerScrollWheel, { passive: false });
            }
        }
        if (prevProps.disabled !== this.props.disabled && !this.props.disabled) {
            this.updateInnerElement();
        }
        if (prevProps.showScrollBar !== this.props.showScrollBar) {
            if (this.props.showScrollBar === 'always') {
                this.setState({ isScrollBarXVisible: true, isScrollBarYVisible: true });
            }
            else if (this.props.showScrollBar === 'never') {
                this.setState({ isScrollBarXVisible: false, isScrollBarYVisible: false });
            }
        }
    };
    ScrollContainer.prototype.render = function () {
        this.styles = getStyles(this.emotion);
        var props = this.props;
        if (this.props.disabled) {
            return this.props.children;
        }
        var innerStyle = {
            scrollBehavior: this.getProps().scrollBehaviour,
            maxHeight: props.maxHeight,
            maxWidth: props.maxWidth,
        };
        var scrollbarY = this.renderScrollbar('y');
        var scrollbarX = this.renderScrollbar('x');
        return (React.createElement(CommonWrapper, __assign({ rootNodeRef: this.setRootNode }, this.props),
            React.createElement("div", { "data-tid": ScrollContainerDataTids.root, className: this.styles.root(), onMouseMove: this.handleMouseMove, onMouseLeave: this.handleMouseLeave },
                scrollbarY,
                scrollbarX,
                React.createElement("div", { style: innerStyle, ref: this.refInner, className: this.cx(this.styles.inner(), globalClasses.inner), "data-tid": ScrollContainerDataTids.inner, onScroll: this.handleNativeScroll }, props.children))));
    };
    /**
     * @public
     * @param {Element} element
     */
    ScrollContainer.prototype.scrollTo = function (element) {
        if (!element || !this.inner) {
            return;
        }
        this.inner.scrollLeft = element.offsetLeft;
        this.inner.scrollTop = getScrollYOffset(element, this.inner);
    };
    /**
     * @public
     */
    ScrollContainer.prototype.scrollToTop = function () {
        if (!this.inner) {
            return;
        }
        this.inner.scrollTop = 0;
    };
    /**
     * @public
     */
    ScrollContainer.prototype.scrollToBottom = function () {
        if (!this.inner) {
            return;
        }
        this.inner.scrollTop = this.inner.scrollHeight - this.inner.offsetHeight;
    };
    /**
     * @public
     */
    ScrollContainer.prototype.scrollToLeft = function () {
        if (!this.inner) {
            return;
        }
        this.inner.scrollLeft = 0;
    };
    /**
     * @public
     */
    ScrollContainer.prototype.scrollToRight = function () {
        if (!this.inner) {
            return;
        }
        this.inner.scrollLeft = this.inner.scrollWidth - this.inner.offsetWidth;
    };
    ScrollContainer.prototype.hasScrollBar = function (axis) {
        if (!this.inner) {
            return false;
        }
        return axis === 'x'
            ? this.inner.offsetWidth < this.inner.scrollWidth
            : this.inner.offsetHeight < this.inner.scrollHeight;
    };
    var ScrollContainer_1;
    ScrollContainer.__KONTUR_REACT_UI__ = 'ScrollContainer';
    ScrollContainer.displayName = 'ScrollContainer';
    ScrollContainer.defaultProps = {
        invert: false,
        scrollBehaviour: 'auto',
        preventWindowScroll: false,
        disableAnimations: isTestEnv,
        hideScrollBarDelay: 500,
        showScrollBar: 'always',
    };
    ScrollContainer = ScrollContainer_1 = __decorate([
        withRenderEnvironment,
        rootNode
    ], ScrollContainer);
    return ScrollContainer;
}(React.Component));
export { ScrollContainer };
//# sourceMappingURL=ScrollContainer.js.map