import * as i0 from '@angular/core';
import { Injectable, NgModule } from '@angular/core';
import * as i1 from 'ng-devui/window-ref';
import { WindowRefModule } from 'ng-devui/window-ref';

class PositionService {
    constructor(documentRef, windowRef) {
        this.documentRef = documentRef;
        this.windowRef = windowRef;
    }
    position(element, round = true) {
        let elPosition;
        let parentOffset = { width: 0, height: 0, top: 0, bottom: 0, left: 0, right: 0 };
        if (this.getStyle(element, 'position') === 'fixed') {
            elPosition = element.getBoundingClientRect();
        }
        else {
            const offsetParentEl = this.offsetParent(element);
            elPosition = this.offset(element, false);
            if (offsetParentEl !== this.documentRef.documentElement) {
                parentOffset = this.offset(offsetParentEl, false);
            }
            parentOffset.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
            parentOffset.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
        }
        elPosition.top -= parentOffset.top;
        elPosition.bottom -= parentOffset.top;
        elPosition.left -= parentOffset.left;
        elPosition.right -= parentOffset.left;
        if (round) {
            elPosition.top = Math.round(elPosition.top);
            elPosition.bottom = Math.round(elPosition.bottom);
            elPosition.left = Math.round(elPosition.left);
            elPosition.right = Math.round(elPosition.right);
        }
        return elPosition;
    }
    offset(element, round = true) {
        const elBcr = element.getBoundingClientRect();
        const viewportOffset = {
            top: this.windowRef.pageYOffset - this.documentRef.documentElement.clientTop,
            left: this.windowRef.pageXOffset - this.documentRef.documentElement.clientLeft
        };
        const elOffset = {
            height: elBcr.height || element.offsetHeight,
            width: elBcr.width || element.offsetWidth,
            top: elBcr.top + viewportOffset.top,
            bottom: elBcr.bottom + viewportOffset.top,
            left: elBcr.left + viewportOffset.left,
            right: elBcr.right + viewportOffset.left
        };
        if (round) {
            elOffset.height = Math.round(elOffset.height);
            elOffset.width = Math.round(elOffset.width);
            elOffset.top = Math.round(elOffset.top);
            elOffset.bottom = Math.round(elOffset.bottom);
            elOffset.left = Math.round(elOffset.left);
            elOffset.right = Math.round(elOffset.right);
        }
        return elOffset;
    }
    getScrollParent(element) {
        let style = getComputedStyle(element);
        const excludeStaticParent = style.position === 'absolute';
        const overflowRegex = /(auto|scroll|hidden)/;
        if (style.position === 'fixed') {
            return this.documentRef.body;
        }
        for (let parent = element; (parent = parent.parentElement); parent.parentElement !== this.documentRef.body) {
            style = getComputedStyle(parent);
            if (excludeStaticParent && style.position === 'static') {
                continue;
            }
            if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
                return parent;
            }
        }
        return this.documentRef.body;
    }
    positionElements(hostElement, targetElement, placement, appendToBody) {
        const hostElPosition = appendToBody ? this.offset(hostElement, false) : this.position(hostElement, false);
        const shiftWidth = {
            left: hostElPosition.left,
            center: hostElPosition.left + hostElPosition.width / 2 - targetElement.offsetWidth / 2,
            right: hostElPosition.left + hostElPosition.width
        };
        const shiftHeight = {
            top: hostElPosition.top,
            center: hostElPosition.top + hostElPosition.height / 2 - targetElement.offsetHeight / 2,
            bottom: hostElPosition.top + hostElPosition.height
        };
        const targetElBCR = targetElement.getBoundingClientRect();
        const targetElPosition = {
            height: targetElBCR.height || targetElement.offsetHeight,
            width: targetElBCR.width || targetElement.offsetWidth,
            top: 0,
            bottom: targetElBCR.height || targetElement.offsetHeight,
            left: 0,
            right: targetElBCR.width || targetElement.offsetWidth
        };
        let placementPrimary;
        let placementSecondary;
        if (Array.isArray(placement)) {
            const targetPlacement = this.getPlacement(hostElement, targetElement, placement);
            placementPrimary = targetPlacement[0];
            placementSecondary = targetPlacement[1];
        }
        else {
            placementPrimary = (placement === null || placement === void 0 ? void 0 : placement.split('-')[0]) || 'top';
            placementSecondary = (placement === null || placement === void 0 ? void 0 : placement.split('-')[1]) || 'center';
        }
        switch (placementPrimary) {
            case 'top':
                targetElPosition.top = hostElPosition.top - targetElement.offsetHeight;
                targetElPosition.bottom += hostElPosition.top - targetElement.offsetHeight;
                targetElPosition.left = placementSecondary === 'right'
                    ? shiftWidth[placementSecondary] - targetElement.offsetWidth : shiftWidth[placementSecondary];
                targetElPosition.right += shiftWidth[placementSecondary];
                break;
            case 'bottom':
                targetElPosition.top = shiftHeight[placementPrimary];
                targetElPosition.bottom += shiftHeight[placementPrimary];
                targetElPosition.left = placementSecondary === 'right'
                    ? shiftWidth[placementSecondary] - targetElement.offsetWidth : shiftWidth[placementSecondary];
                targetElPosition.right += shiftWidth[placementSecondary];
                break;
            case 'left':
                targetElPosition.top = placementSecondary === 'bottom'
                    ? shiftHeight[placementSecondary] - targetElement.offsetHeight : shiftHeight[placementSecondary];
                targetElPosition.bottom += shiftHeight[placementSecondary];
                targetElPosition.left = hostElPosition.left - targetElement.offsetWidth;
                targetElPosition.right += hostElPosition.left - targetElement.offsetWidth;
                break;
            case 'right':
                targetElPosition.top = placementSecondary === 'bottom'
                    ? shiftHeight[placementSecondary] - targetElement.offsetHeight : shiftHeight[placementSecondary];
                targetElPosition.bottom += shiftHeight[placementSecondary];
                targetElPosition.left = shiftWidth[placementPrimary];
                targetElPosition.right += shiftWidth[placementPrimary];
                break;
        }
        targetElPosition.top = Math.round(targetElPosition.top);
        targetElPosition.bottom = Math.round(targetElPosition.bottom);
        targetElPosition.left = Math.round(targetElPosition.left);
        targetElPosition.right = Math.round(targetElPosition.right);
        targetElPosition.placementPrimary = placementPrimary;
        targetElPosition.placementSecondary = placementSecondary;
        return targetElPosition;
    }
    // 根据传入数组选取第一个合适的位置
    getPlacement(hostElement, targetElement, placement) {
        const hostElPosition = this.offset(hostElement, false);
        const shiftWidth = {
            left: hostElPosition.left,
            center: hostElPosition.left + hostElPosition.width / 2 - targetElement.offsetWidth / 2,
            right: hostElPosition.left + hostElPosition.width
        };
        const shiftHeight = {
            top: hostElPosition.top,
            center: hostElPosition.top + hostElPosition.height / 2 - targetElement.offsetHeight / 2,
            bottom: hostElPosition.top + hostElPosition.height
        };
        let placementPrimary = placement[0].split('-')[0] || 'top';
        let placementSecondary = placement[0].split('-')[1] || 'center';
        for (let i = 0; i < placement.length; i++) {
            const placementPrimaryTemp = placement[i].split('-')[0] || 'top';
            const placementSecondaryTemp = placement[i].split('-')[1] || 'center';
            let top;
            let left;
            switch (placementPrimaryTemp) {
                case 'top':
                    top = hostElPosition.top - targetElement.offsetHeight;
                    left = placementSecondaryTemp === 'right'
                        ? shiftWidth[placementSecondaryTemp] - targetElement.offsetWidth : shiftWidth[placementSecondary];
                    break;
                case 'bottom':
                    top = shiftHeight[placementPrimaryTemp];
                    left = placementSecondaryTemp === 'right'
                        ? shiftWidth[placementSecondaryTemp] - targetElement.offsetWidth : shiftWidth[placementSecondary];
                    break;
                case 'left':
                    top = placementSecondaryTemp === 'bottom'
                        ? shiftHeight[placementSecondaryTemp] - targetElement.offsetHeight : shiftHeight[placementSecondary];
                    left = hostElPosition.left - targetElement.offsetWidth;
                    break;
                case 'right':
                    top = placementSecondaryTemp === 'bottom'
                        ? shiftHeight[placementSecondaryTemp] - targetElement.offsetHeight : shiftHeight[placementSecondary];
                    left = shiftWidth[placementPrimaryTemp];
                    break;
            }
            if (this.isInViewPort(targetElement, { offsetLeft: left, offsetTop: top })) {
                placementPrimary = placement[i].split('-')[0] || 'top';
                placementSecondary = placement[i].split('-')[1] || 'center';
                return [placementPrimary, placementSecondary];
            }
        }
        return [placementPrimary, placementSecondary];
    }
    isInViewPort(ele, { offsetLeft, offsetTop }) {
        const targetElBCR = ele.getBoundingClientRect();
        const viewPortHeight = this.windowRef.innerHeight || this.documentRef.documentElement.clientHeight
            || this.documentRef.body.clientHeight;
        const viewPortWidth = this.windowRef.innerWidth || this.documentRef.documentElement.clientWidth || this.documentRef.body.clientWidth;
        const height = targetElBCR.height || targetElBCR.offsetHeight;
        const width = targetElBCR.width || targetElBCR.offsetWidth;
        offsetTop = offsetTop || ele.offsetTop;
        const scrollTop = this.documentRef.documentElement.scrollTop || this.documentRef.body.scrollTop;
        const top = offsetTop - scrollTop;
        offsetLeft = offsetLeft || ele.offsetLeft;
        const scrollLeft = this.documentRef.documentElement.scrollLeft || this.documentRef.body.scrollLeft;
        const left = offsetLeft - scrollLeft;
        return top + height <= viewPortHeight && top > 0 && left + width <= viewPortWidth && left > 0;
    }
    getStyle(element, prop) {
        return this.windowRef.getComputedStyle(element)[prop];
    }
    isStaticPositioned(element) {
        return (this.getStyle(element, 'position') || 'static') === 'static';
    }
    offsetParent(element) {
        let offsetParentEl = element.offsetParent || this.documentRef.documentElement;
        while (offsetParentEl && offsetParentEl !== this.documentRef.documentElement && this.isStaticPositioned(offsetParentEl)) {
            offsetParentEl = offsetParentEl.offsetParent;
        }
        return offsetParentEl || this.documentRef.documentElement;
    }
}
PositionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: PositionService, deps: [{ token: i1.DocumentRef }, { token: i1.WindowRef }], target: i0.ɵɵFactoryTarget.Injectable });
PositionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: PositionService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: PositionService, decorators: [{
            type: Injectable
        }], ctorParameters: function () { return [{ type: i1.DocumentRef }, { type: i1.WindowRef }]; } });

class PositioningModule {
}
PositioningModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: PositioningModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
PositioningModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.0", ngImport: i0, type: PositioningModule, imports: [WindowRefModule] });
PositioningModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: PositioningModule, providers: [PositionService], imports: [WindowRefModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: PositioningModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [WindowRefModule],
                    providers: [PositionService]
                }]
        }] });

/**
 * Generated bundle index. Do not edit.
 */

export { PositionService, PositioningModule };
//# sourceMappingURL=ng-devui-position.mjs.map
