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;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import { Inject, Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { EL_DOCUMENT } from '../../../theme.options';
import { ElFlexibleConnectedPositionStrategy, ElOverlayPositionBuilder, ElPlatform, } from './mapping';
import { ElOverlayContainerAdapter } from '../adapter/overlay-container-adapter';
import { ElViewportRulerAdapter } from '../adapter/viewport-ruler-adapter';
import { ElGlobalLogicalPosition } from './position-helper';
import { GlobalPositionStrategy } from '@angular/cdk/overlay';
export var ElAdjustment;
(function (ElAdjustment) {
    ElAdjustment["NOOP"] = "noop";
    ElAdjustment["CLOCKWISE"] = "clockwise";
    ElAdjustment["COUNTERCLOCKWISE"] = "counterclockwise";
    ElAdjustment["VERTICAL"] = "vertical";
    ElAdjustment["HORIZONTAL"] = "horizontal";
})(ElAdjustment || (ElAdjustment = {}));
export var ElPosition;
(function (ElPosition) {
    ElPosition["TOP"] = "top";
    ElPosition["BOTTOM"] = "bottom";
    ElPosition["LEFT"] = "left";
    ElPosition["RIGHT"] = "right";
    ElPosition["START"] = "start";
    ElPosition["END"] = "end";
    ElPosition["TOP_END"] = "top-end";
    ElPosition["TOP_START"] = "top-start";
    ElPosition["BOTTOM_END"] = "bottom-end";
    ElPosition["BOTTOM_START"] = "bottom-start";
    ElPosition["END_TOP"] = "end-top";
    ElPosition["END_BOTTOM"] = "end-bottom";
    ElPosition["START_TOP"] = "start-top";
    ElPosition["START_BOTTOM"] = "start-bottom";
})(ElPosition || (ElPosition = {}));
const POSITIONS = {
    [ElPosition.RIGHT](offset) {
        return { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: offset };
    },
    [ElPosition.BOTTOM](offset) {
        return { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: offset };
    },
    [ElPosition.LEFT](offset) {
        return { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -offset };
    },
    [ElPosition.TOP](offset) {
        return { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -offset };
    },
    [ElPosition.START](offset) {
        return this[ElPosition.LEFT](offset);
    },
    [ElPosition.END](offset) {
        return this[ElPosition.RIGHT](offset);
    },
    [ElPosition.END_TOP](offset) {
        return { originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom', offsetX: offset };
    },
    [ElPosition.END_BOTTOM](offset) {
        return { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top', offsetX: offset };
    },
    [ElPosition.BOTTOM_START](offset) {
        return { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: offset };
    },
    [ElPosition.BOTTOM_END](offset) {
        return { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: offset };
    },
    [ElPosition.START_TOP](offset) {
        return { originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom', offsetX: -offset };
    },
    [ElPosition.START_BOTTOM](offset) {
        return { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top', offsetX: -offset };
    },
    [ElPosition.TOP_START](offset) {
        return { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -offset };
    },
    [ElPosition.TOP_END](offset) {
        return { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -offset };
    },
};
const COUNTER_CLOCKWISE_POSITIONS = [
    ElPosition.TOP,
    ElPosition.TOP_END,
    ElPosition.TOP_START,
    ElPosition.START,
    ElPosition.START_TOP,
    ElPosition.START_BOTTOM,
    ElPosition.BOTTOM,
    ElPosition.BOTTOM_START,
    ElPosition.BOTTOM_END,
    ElPosition.END,
    ElPosition.END_BOTTOM,
    ElPosition.END_TOP,
];
const CLOCKWISE_POSITIONS = [
    ElPosition.TOP,
    ElPosition.TOP_START,
    ElPosition.TOP_END,
    ElPosition.END,
    ElPosition.END_TOP,
    ElPosition.END_BOTTOM,
    ElPosition.BOTTOM,
    ElPosition.BOTTOM_END,
    ElPosition.BOTTOM_START,
    ElPosition.START,
    ElPosition.START_BOTTOM,
    ElPosition.START_TOP,
];
const VERTICAL_POSITIONS = [ElPosition.BOTTOM, ElPosition.TOP];
const HORIZONTAL_POSITIONS = [ElPosition.START, ElPosition.END];
function comparePositions(p1, p2) {
    return p1.originX === p2.originX
        && p1.originY === p2.originY
        && p1.overlayX === p2.overlayX
        && p1.overlayY === p2.overlayY;
}
/**
 * The main idea of the adjustable connected strategy is to provide predefined set of positions for your overlay.
 * You have to provide adjustment and appropriate strategy will be chosen in runtime.
 * */
export class ElAdjustableConnectedPositionStrategy extends ElFlexibleConnectedPositionStrategy {
    constructor() {
        super(...arguments);
        this._offset = 15;
        this.positionChange = this.positionChanges.pipe(map((positionChange) => positionChange.connectionPair), map((connectionPair) => {
            return this.appliedPositions.find(({ connectedPosition }) => {
                return comparePositions(connectedPosition, connectionPair);
            }).key;
        }));
    }
    attach(overlayRef) {
        /**
         * We have to apply positions before attach because super.attach() validates positions and crashes app
         * if no positions provided.
         * */
        this.applyPositions();
        super.attach(overlayRef);
    }
    apply() {
        this.applyPositions();
        super.apply();
    }
    position(position) {
        this._position = position;
        return this;
    }
    adjustment(adjustment) {
        this._adjustment = adjustment;
        return this;
    }
    offset(offset) {
        this._offset = offset;
        return this;
    }
    applyPositions() {
        const positions = this.createPositions();
        this.persistChosenPositions(positions);
        this.withPositions(this.appliedPositions.map(({ connectedPosition }) => connectedPosition));
    }
    createPositions() {
        switch (this._adjustment) {
            case ElAdjustment.NOOP:
                return [this._position];
            case ElAdjustment.CLOCKWISE:
                return this.reorderPreferredPositions(CLOCKWISE_POSITIONS);
            case ElAdjustment.COUNTERCLOCKWISE:
                return this.reorderPreferredPositions(COUNTER_CLOCKWISE_POSITIONS);
            case ElAdjustment.HORIZONTAL:
                return this.reorderPreferredPositions(HORIZONTAL_POSITIONS);
            case ElAdjustment.VERTICAL:
                return this.reorderPreferredPositions(VERTICAL_POSITIONS);
        }
    }
    persistChosenPositions(positions) {
        this.appliedPositions = positions.map(position => ({
            key: position,
            connectedPosition: POSITIONS[position](this._offset),
        }));
    }
    reorderPreferredPositions(positions) {
        const startPositionIndex = positions.indexOf(this._position);
        const firstPart = positions.slice(startPositionIndex);
        const secondPart = positions.slice(0, startPositionIndex);
        return firstPart.concat(secondPart);
    }
}
export class ElGlobalPositionStrategy extends GlobalPositionStrategy {
    position(position) {
        switch (position) {
            case ElGlobalLogicalPosition.TOP_START:
                return this.top().left();
            case ElGlobalLogicalPosition.TOP_END:
                return this.top().right();
            case ElGlobalLogicalPosition.BOTTOM_START:
                return this.bottom().left();
            case ElGlobalLogicalPosition.BOTTOM_END:
                return this.bottom().right();
        }
    }
}
let ElPositionBuilderService = class ElPositionBuilderService {
    constructor(document, viewportRuler, platform, positionBuilder, overlayContainer) {
        this.document = document;
        this.viewportRuler = viewportRuler;
        this.platform = platform;
        this.positionBuilder = positionBuilder;
        this.overlayContainer = overlayContainer;
    }
    global() {
        return new ElGlobalPositionStrategy();
    }
    connectedTo(elementRef) {
        return new ElAdjustableConnectedPositionStrategy(elementRef, this.viewportRuler, this.document, this.platform, this.overlayContainer)
            .withFlexibleDimensions(false)
            .withPush(false);
    }
};
ElPositionBuilderService = __decorate([
    Injectable(),
    __param(0, Inject(EL_DOCUMENT)),
    __metadata("design:paramtypes", [Object, ElViewportRulerAdapter,
        ElPlatform,
        ElOverlayPositionBuilder,
        ElOverlayContainerAdapter])
], ElPositionBuilderService);
export { ElPositionBuilderService };
//# sourceMappingURL=overlay-position.js.map