import { __extends } from "tslib";
import { mousePositionElement } from '../../../utils/mouse/mouse';
import { polyFillActive } from '../../../utils/polyfills/drag-and-drop.polyfill';
import { DRAGGABLE_ALLOW_SCROLL_NAME } from '../../directive-names';
import { MDOMPlugin, MElementDomPlugin } from '../../domPlugin';
import { ScrollTo, ScrollToDuration } from '../../scroll-to/scroll-to-lib';
export var MDraggableAllowScrollDirection;
(function (MDraggableAllowScrollDirection) {
    MDraggableAllowScrollDirection["Top"] = "top";
    MDraggableAllowScrollDirection["Bottom"] = "bottom";
})(MDraggableAllowScrollDirection || (MDraggableAllowScrollDirection = {}));
// Naive implementation for a single use case: allow autoscroll on a fixed element that appears at the absolute top of the viewport.
// Furthermore, the user must be dragging something for it to work.
var MDraggableAllowScroll = /** @class */ (function (_super) {
    __extends(MDraggableAllowScroll, _super);
    function MDraggableAllowScroll() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    MDraggableAllowScroll.prototype.attach = function (mount) {
        var _this = this;
        if (polyFillActive.dragDrop) {
            return;
        }
        // This is cheesy but we only need to fix the scrolling behavior if the polyfill is not active.
        // The polyfill already includes a scroll behavior for mobile devices.  However, it doesn't allow to enable the scrolling behavior for desktops.
        this.cleanUpOptions();
        if (this.options.allowScroll) {
            mount(function () {
                _this.addEventListener('dragover', function (event) { return _this.handleScroll(event); });
            });
        }
    };
    MDraggableAllowScroll.prototype.update = function (options, refresh) {
        var _this = this;
        this.cleanUpOptions();
        if (this.options.allowScroll) {
            refresh(function () { return _this._options = options; });
        }
    };
    MDraggableAllowScroll.prototype.detach = function () {
        this.doCleanUp();
    };
    MDraggableAllowScroll.prototype.doCleanUp = function () {
        this.element.style.display = '';
        this.cancelScroll();
    };
    MDraggableAllowScroll.prototype.cleanUpOptions = function () {
        if (this._options === undefined) {
            this._options = { allowScroll: true, scrollDirection: MDraggableAllowScrollDirection.Top };
        }
        if (this._options.allowScroll === undefined) {
            this._options.allowScroll = true;
        }
        if (this._options.scrollDirection === undefined) {
            this._options.scrollDirection = MDraggableAllowScrollDirection.Top;
        }
    };
    MDraggableAllowScroll.prototype.handleScroll = function (event) {
        var _this = this;
        var watchMouseMove = function (event) {
            if ((!_this.shouldScroll(event) && _this.activeScroll) || MDraggableAllowScroll.currentDraggableScroll !== _this) {
                if (_this.activeScroll) {
                    _this.cancelScroll();
                }
                document.removeEventListener('dragover', watchMouseMove);
            }
            else if (!_this.activeScroll) {
                _this.activateScroll();
            }
        };
        if (this.shouldScroll(event) && window.getComputedStyle(this.element).position === 'fixed') {
            if (MDraggableAllowScroll.currentDraggableScroll && MDraggableAllowScroll.currentDraggableScroll !== this) {
                MDraggableAllowScroll.currentDraggableScroll.doCleanUp();
                MDraggableAllowScroll.currentDraggableScroll = undefined;
                return;
            }
            MDraggableAllowScroll.currentDraggableScroll = this;
            document.addEventListener('dragover', watchMouseMove);
        }
    };
    MDraggableAllowScroll.prototype.shouldScroll = function (event) {
        var scrollThreshold = this.element.offsetHeight;
        switch (this.options.scrollDirection) {
            case MDraggableAllowScrollDirection.Top: return event.clientY < scrollThreshold;
            case MDraggableAllowScrollDirection.Bottom: return mousePositionElement(event, this.element).y >= this.element.offsetHeight - scrollThreshold;
            default: throw new Error("Unhandled value for scrollDirection: " + this.options.scrollDirection);
        }
    };
    MDraggableAllowScroll.prototype.activateScroll = function () {
        switch (this.options.scrollDirection) {
            case MDraggableAllowScrollDirection.Top:
                // tslint:disable-next-line: deprecation
                this.activeScroll = new ScrollTo().scrollToTop(document.documentElement, ScrollToDuration.Slower);
                break;
            case MDraggableAllowScrollDirection.Bottom:
                // tslint:disable-next-line: deprecation
                this.activeScroll = new ScrollTo().scrollToBottom(document.documentElement, ScrollToDuration.Slower);
                break;
            default: throw new Error("Unhandled value for scrollDirection: " + this.options.scrollDirection);
        }
    };
    MDraggableAllowScroll.prototype.cancelScroll = function () {
        if (this.activeScroll) {
            this.activeScroll.cancel();
            this.activeScroll = undefined;
            this.doCleanUp();
        }
    };
    MDraggableAllowScroll.defaultMountPoint = '__mdraggableallowscroll__';
    return MDraggableAllowScroll;
}(MElementDomPlugin));
export { MDraggableAllowScroll };
var extractOptions = function (binding) {
    return {
        allowScroll: binding.value,
        scrollDirection: binding.arg
    };
};
var Directive = {
    inserted: function (element, binding) {
        MDOMPlugin.attach(MDraggableAllowScroll, element, extractOptions(binding));
    },
    update: function (element, binding) {
        MDOMPlugin.attach(MDraggableAllowScroll, element, extractOptions(binding));
    },
    unbind: function (element) {
        MDOMPlugin.detach(MDraggableAllowScroll, element);
    }
};
var DraggableAllowScrollPlugin = {
    install: function (v) {
        v.directive(DRAGGABLE_ALLOW_SCROLL_NAME, Directive);
    }
};
export default DraggableAllowScrollPlugin;
//# sourceMappingURL=draggable-allow-scroll.js.map