"use strict";

Object.defineProperty(exports, "__esModule", {
    value: !0
}), exports.ZoomScaleManager = void 0;

const DataZoomIntegration_1 = require("./DataZoomIntegration"), EVENT_TYPE_1 = require("../ts-types/EVENT_TYPE");

class ZoomScaleManager {
    constructor(gantt, config) {
        this.currentLevelIndex = 0, this.levelBoundaries = [], this.globalMinMillisecondsPerPixel = 0, 
        this.globalMaxMillisecondsPerPixel = 0, this.dataZoomIntegration = null, this.gantt = gantt;
        const finalConfig = Object.assign({
            enabled: !0,
            levels: []
        }, config);
        if (this.config = finalConfig, this.initializeZoomLimits(), this.sortLevelsByCoarseness(), 
        this.calculateGlobalMillisecondsPerPixelRange(), this.calculateLevelBoundaries(), 
        this.updateZoomLimits(), this.config.levels.length > 0) {
            const initialMillisecondsPerPixel = this.calculateInitialMillisecondsPerPixel();
            this.initializeWithMillisecondsPerPixel(initialMillisecondsPerPixel);
        }
        this.initializeDataZoomIfNeeded();
    }
    initializeZoomLimits() {
        var _a, _b, _c, _d, _e;
        const existingZoom = this.gantt.parsedOptions.zoom, zoomScaleConfig = this.config;
        this.gantt.parsedOptions.zoom = {
            minMillisecondsPerPixel: null !== (_b = null !== (_a = null == existingZoom ? void 0 : existingZoom.minMillisecondsPerPixel) && void 0 !== _a ? _a : zoomScaleConfig.minMillisecondsPerPixel) && void 0 !== _b ? _b : 1e3,
            maxMillisecondsPerPixel: null !== (_d = null !== (_c = null == existingZoom ? void 0 : existingZoom.maxMillisecondsPerPixel) && void 0 !== _c ? _c : zoomScaleConfig.maxMillisecondsPerPixel) && void 0 !== _d ? _d : 6e6,
            step: null !== (_e = zoomScaleConfig.step) && void 0 !== _e ? _e : .015
        };
    }
    initializeDataZoomIfNeeded() {
        var _a, _b, _c;
        const dataZoomConfig = this.config.dataZoomAxis;
        if (!(null == dataZoomConfig ? void 0 : dataZoomConfig.enabled)) return;
        const finalConfig = {
            containerId: dataZoomConfig.containerId,
            width: dataZoomConfig.width,
            height: null !== (_a = dataZoomConfig.height) && void 0 !== _a ? _a : 30,
            x: dataZoomConfig.x,
            y: null !== (_b = dataZoomConfig.y) && void 0 !== _b ? _b : 0,
            delayTime: null !== (_c = dataZoomConfig.delayTime) && void 0 !== _c ? _c : 10
        };
        try {
            this.dataZoomIntegration = new DataZoomIntegration_1.DataZoomIntegration(this.gantt, finalConfig);
        } catch (error) {}
    }
    handleTableWidthChange() {
        this.dataZoomIntegration && this.dataZoomIntegration.updateResponsive();
    }
    sortLevelsByCoarseness() {
        this.config.levels.length <= 1 || this.config.levels.sort(((levelA, levelB) => {
            const minUnitA = this.findMinTimeUnit(levelA), minUnitB = this.findMinTimeUnit(levelB), unitMsA = this.getUnitMilliseconds(minUnitA.unit, minUnitA.step);
            return this.getUnitMilliseconds(minUnitB.unit, minUnitB.step) - unitMsA;
        }));
    }
    calculateGlobalMillisecondsPerPixelRange() {
        const levels = this.config.levels;
        if (0 === levels.length) return;
        let maxMinUnit = null, maxMinUnitMs = 0, minMinUnit = null, minMinUnitMs = 1 / 0;
        for (const level of levels) {
            const minUnit = this.findMinTimeUnit(level), unitMs = this.getUnitMilliseconds(minUnit.unit, minUnit.step);
            unitMs > maxMinUnitMs && (maxMinUnitMs = unitMs, maxMinUnit = minUnit), unitMs < minMinUnitMs && (minMinUnitMs = unitMs, 
            minMinUnit = minUnit);
        }
        if (maxMinUnit && minMinUnit && (this.globalMinMillisecondsPerPixel = minMinUnitMs / 120, 
        this.globalMaxMillisecondsPerPixel = maxMinUnitMs / 150, this.globalMinMillisecondsPerPixel > this.globalMaxMillisecondsPerPixel)) {
            const temp = this.globalMinMillisecondsPerPixel;
            this.globalMinMillisecondsPerPixel = this.globalMaxMillisecondsPerPixel, this.globalMaxMillisecondsPerPixel = temp;
        }
    }
    calculateLevelBoundaries() {
        const levelCount = this.config.levels.length;
        if (0 === levelCount) return;
        this.levelBoundaries = [];
        const idealBoundaries = [];
        idealBoundaries[levelCount] = this.globalMinMillisecondsPerPixel;
        for (let i = levelCount - 1; i >= 1; i--) {
            const currentLevel = this.config.levels[i], currentMinUnit = this.findMinTimeUnit(currentLevel), idealBoundary = this.getUnitMilliseconds(currentMinUnit.unit, currentMinUnit.step) / this.getMinColWidthForUnit(currentMinUnit.unit, currentMinUnit.step);
            idealBoundaries[i] = idealBoundary;
        }
        idealBoundaries[0] = this.globalMaxMillisecondsPerPixel, this.levelBoundaries = [ ...idealBoundaries ];
        for (let i = 1; i < levelCount; i++) {
            if (this.levelBoundaries[i] >= this.levelBoundaries[i - 1]) {
                const prevBoundary = this.levelBoundaries[i - 1], nextBoundary = this.levelBoundaries[i + 1] || this.globalMinMillisecondsPerPixel;
                this.levelBoundaries[i] = (prevBoundary + nextBoundary) / 2;
            }
            this.levelBoundaries[i] = Math.max(this.globalMinMillisecondsPerPixel, Math.min(this.globalMaxMillisecondsPerPixel, this.levelBoundaries[i]));
        }
    }
    updateZoomLimits() {
        this.gantt.parsedOptions.zoom || (this.gantt.parsedOptions.zoom = {}), this.gantt.parsedOptions.zoom.minMillisecondsPerPixel = this.globalMinMillisecondsPerPixel, 
        this.gantt.parsedOptions.zoom.maxMillisecondsPerPixel = this.globalMaxMillisecondsPerPixel;
    }
    getGlobalMinMillisecondsPerPixel() {
        return this.globalMinMillisecondsPerPixel;
    }
    getGlobalMaxMillisecondsPerPixel() {
        return this.globalMaxMillisecondsPerPixel;
    }
    calculateInitialMillisecondsPerPixel() {
        return this.globalMinMillisecondsPerPixel + .4 * (this.globalMaxMillisecondsPerPixel - this.globalMinMillisecondsPerPixel);
    }
    initializeWithMillisecondsPerPixel(millisecondsPerPixel) {
        if (0 === this.config.levels.length) return;
        const optimalLevel = this.findOptimalLevel(millisecondsPerPixel);
        this.setInitialLevel(optimalLevel);
    }
    setInitialLevel(levelIndex) {
        if (levelIndex < 0 || levelIndex >= this.config.levels.length) return;
        const levelScales = this.config.levels[levelIndex];
        levelScales && 0 !== levelScales.length && (this.gantt.options.timelineHeader.scales = [ ...levelScales ], 
        this.currentLevelIndex = levelIndex);
    }
    findOptimalLevel(millisecondsPerPixel) {
        const clampedMillisecondsPerPixel = Math.max(this.globalMinMillisecondsPerPixel, Math.min(this.globalMaxMillisecondsPerPixel, millisecondsPerPixel));
        for (let i = 0; i < this.levelBoundaries.length - 1; i++) if (clampedMillisecondsPerPixel <= this.levelBoundaries[i] && clampedMillisecondsPerPixel > this.levelBoundaries[i + 1]) return i;
        return this.config.levels.length - 1;
    }
    switchToLevel(levelIndex) {
        if (levelIndex < 0 || levelIndex >= this.config.levels.length) return !1;
        if (this.currentLevelIndex === levelIndex) return !0;
        const levelScales = this.config.levels[levelIndex];
        if (!levelScales || 0 === levelScales.length) return !1;
        try {
            return this.gantt.updateScales([ ...levelScales ]), this.currentLevelIndex = levelIndex, 
            this.gantt.recalculateTimeScale(), !0;
        } catch (error) {
            return !1;
        }
    }
    findMinTimeUnit(scales) {
        let minUnit = scales[0], minUnitMs = this.getUnitMilliseconds(minUnit.unit, minUnit.step);
        for (const scale of scales) {
            const unitMs = this.getUnitMilliseconds(scale.unit, scale.step);
            unitMs < minUnitMs && (minUnitMs = unitMs, minUnit = scale);
        }
        return minUnit;
    }
    getUnitMilliseconds(unit, step) {
        const unitMs = {
            second: 1e3,
            minute: 6e4,
            hour: 36e5,
            day: 864e5,
            week: 6048e5,
            month: 2592e6,
            quarter: 7776e6,
            year: 31536e6
        };
        return (unitMs[unit] || unitMs.day) * step;
    }
    getMinColWidthForUnit(unit, step) {
        switch (unit) {
          case "hour":
            return step > 1 ? 120 : 60;

          case "minute":
            return 80;

          case "second":
            return 100;

          default:
            return 60;
        }
    }
    getCurrentLevel() {
        return this.currentLevelIndex;
    }
    getInitialMillisecondsPerPixel() {
        return this.calculateInitialMillisecondsPerPixel();
    }
    getCurrentZoomState() {
        if (0 === this.config.levels.length) return null;
        const currentLevel = this.config.levels[this.currentLevelIndex], minUnit = this.findMinTimeUnit(currentLevel), currentMillisecondsPerPixel = this.gantt.getCurrentMillisecondsPerPixel(), currentColWidth = this.getUnitMilliseconds(minUnit.unit, minUnit.step) / currentMillisecondsPerPixel;
        return {
            minUnit: minUnit.unit,
            step: minUnit.step,
            levelNum: this.currentLevelIndex,
            currentColWidth: Math.round(10 * currentColWidth) / 10
        };
    }
    setZoomPosition(params) {
        if (0 === this.config.levels.length) return !1;
        const {minUnit: minUnit, step: step, levelNum: levelNum, colWidth: colWidth} = params;
        let targetMillisecondsPerPixel, targetLevelIndex = null;
        if (void 0 !== minUnit && void 0 !== step) {
            if (targetLevelIndex = this.findLevelByMinUnit(minUnit, step), null === targetLevelIndex) return !1;
        } else {
            if (void 0 === levelNum) return !1;
            if (levelNum < 0 || levelNum >= this.config.levels.length) return !1;
            targetLevelIndex = levelNum;
        }
        if (void 0 !== colWidth) {
            const targetLevel = this.config.levels[targetLevelIndex], targetMinUnit = this.findMinTimeUnit(targetLevel);
            targetMillisecondsPerPixel = this.getUnitMilliseconds(targetMinUnit.unit, targetMinUnit.step) / colWidth;
            const upperBoundary = this.levelBoundaries[targetLevelIndex], lowerBoundary = this.levelBoundaries[targetLevelIndex + 1];
            (targetMillisecondsPerPixel < lowerBoundary || targetMillisecondsPerPixel > upperBoundary) && (targetMillisecondsPerPixel = (upperBoundary + lowerBoundary) / 2);
        } else {
            targetMillisecondsPerPixel = (this.levelBoundaries[targetLevelIndex] + this.levelBoundaries[targetLevelIndex + 1]) / 2;
        }
        return targetLevelIndex !== this.currentLevelIndex && this.switchToLevel(targetLevelIndex), 
        this.gantt.setMillisecondsPerPixel(targetMillisecondsPerPixel), !0;
    }
    findLevelByMinUnit(unit, step) {
        for (let i = 0; i < this.config.levels.length; i++) {
            const level = this.config.levels[i], minUnit = this.findMinTimeUnit(level);
            if (minUnit.unit === unit && minUnit.step === step) return i;
        }
        return null;
    }
    zoomIn(factor = 1.1, center = !0, centerX) {
        this.gantt.zoomByFactor(factor, center, centerX);
    }
    zoomOut(factor = .9, center = !0, centerX) {
        this.gantt.zoomByFactor(factor, center, centerX);
    }
    zoomByPercentage(percentage, center = !0, centerX) {
        const currentMillisecondsPerPixel = this.gantt.getCurrentMillisecondsPerPixel(), targetMillisecondsPerPixel = currentMillisecondsPerPixel - (this.globalMaxMillisecondsPerPixel - this.globalMinMillisecondsPerPixel) * percentage / 100;
        let centerTimePosition;
        center && this.gantt.scenegraph && (void 0 === centerX && (centerX = this.gantt.scenegraph.width / 2), 
        centerTimePosition = (this.gantt.stateManager.scroll.horizontalBarPos + centerX) * currentMillisecondsPerPixel);
        const targetLevel = this.findOptimalLevel(targetMillisecondsPerPixel);
        if (targetLevel !== this.getCurrentLevel() && this.switchToLevel(targetLevel), this.gantt.setMillisecondsPerPixel(targetMillisecondsPerPixel), 
        void 0 !== centerTimePosition && void 0 !== centerX) {
            const newScrollLeft = centerTimePosition / this.gantt.getCurrentMillisecondsPerPixel() - centerX;
            this.gantt.stateManager.setScrollLeft(newScrollLeft);
        }
    }
    getDataZoomIntegration() {
        return this.dataZoomIntegration;
    }
    createDataZoomIntegration(config) {
        return this.dataZoomIntegration && this.dataZoomIntegration.destroy(), this.dataZoomIntegration = new DataZoomIntegration_1.DataZoomIntegration(this.gantt, config), 
        this.dataZoomIntegration;
    }
    destroyDataZoomIntegration() {
        this.dataZoomIntegration && (this.dataZoomIntegration.destroy(), this.dataZoomIntegration = null);
    }
    updateDataZoomResponsive() {
        this.dataZoomIntegration && this.dataZoomIntegration.updateResponsive();
    }
    recalculateTimeScale() {
        const primaryScale = this.gantt.parsedOptions.reverseSortedTimelineScales[0];
        if (!primaryScale) return;
        let msPerStep;
        switch (primaryScale.unit) {
          case "second":
            msPerStep = 1e3 * primaryScale.step;
            break;

          case "minute":
            msPerStep = 6e4 * primaryScale.step;
            break;

          case "hour":
            msPerStep = 36e5 * primaryScale.step;
            break;

          case "day":
          default:
            msPerStep = 864e5 * primaryScale.step;
            break;

          case "week":
            msPerStep = 6048e5 * primaryScale.step;
            break;

          case "month":
            msPerStep = 2592e6 * primaryScale.step;
            break;

          case "quarter":
            msPerStep = 7776e6 * primaryScale.step;
            break;

          case "year":
            msPerStep = 31536e6 * primaryScale.step;
        }
        const newTimelineColWidth = msPerStep / this.gantt.getCurrentMillisecondsPerPixel();
        this.gantt.parsedOptions.timelineColWidth = newTimelineColWidth, this.gantt._generateTimeLineDateMap(), 
        this.gantt.scenegraph && (this.gantt._updateSize(), this.gantt.scenegraph.refreshAll());
    }
    zoomByFactor(factor, keepCenter = !0, centerX) {
        var _a, _b, _c, _d;
        const minMillisecondsPerPixel = null !== (_b = null === (_a = this.gantt.parsedOptions.zoom) || void 0 === _a ? void 0 : _a.minMillisecondsPerPixel) && void 0 !== _b ? _b : 2e5, maxMillisecondsPerPixel = null !== (_d = null === (_c = this.gantt.parsedOptions.zoom) || void 0 === _c ? void 0 : _c.maxMillisecondsPerPixel) && void 0 !== _d ? _d : 3e6, oldMillisecondsPerPixel = this.gantt.getCurrentMillisecondsPerPixel(), oldWidth = this.gantt.parsedOptions.timelineColWidth;
        let centerTimePosition;
        if (keepCenter) {
            void 0 === centerX && (centerX = this.gantt.scenegraph.width / 2);
            const scrollOffsetMs = (this.gantt.stateManager.scroll.horizontalBarPos + centerX) * oldMillisecondsPerPixel;
            centerTimePosition = this.gantt.parsedOptions._minDateTime + scrollOffsetMs;
        }
        const currentMillisecondsPerPixel = this.gantt.getCurrentMillisecondsPerPixel();
        let adjustedFactor = factor;
        const zoomRatio = Math.log(currentMillisecondsPerPixel / 144e4) / Math.log(2);
        if (currentMillisecondsPerPixel < 144e4) {
            const enhancement = Math.pow(1.2, -zoomRatio);
            adjustedFactor = Math.pow(factor, enhancement);
        } else {
            const dampening = Math.pow(.9, zoomRatio);
            adjustedFactor = Math.pow(factor, dampening);
        }
        const newMillisecondsPerPixel = this.gantt.getCurrentMillisecondsPerPixel() / adjustedFactor, clampedMillisecondsPerPixel = Math.max(minMillisecondsPerPixel, Math.min(maxMillisecondsPerPixel, newMillisecondsPerPixel));
        this.gantt.setMillisecondsPerPixel(clampedMillisecondsPerPixel);
        const targetLevel = this.findOptimalLevel(clampedMillisecondsPerPixel);
        if (targetLevel !== this.getCurrentLevel() ? this.switchToLevel(targetLevel) : this.recalculateTimeScale(), 
        keepCenter && void 0 !== centerTimePosition && void 0 !== centerX) {
            const actualMillisecondsPerPixel = this.gantt.getCurrentMillisecondsPerPixel(), newScrollLeft = (centerTimePosition - this.gantt.parsedOptions._minDateTime) / actualMillisecondsPerPixel - centerX;
            this.gantt.stateManager.setScrollLeft(newScrollLeft);
        }
        if (this.gantt.hasListeners(EVENT_TYPE_1.GANTT_EVENT_TYPE.ZOOM)) {
            const actualMillisecondsPerPixel = this.gantt.getCurrentMillisecondsPerPixel();
            this.gantt.fireListeners(EVENT_TYPE_1.GANTT_EVENT_TYPE.ZOOM, {
                oldWidth: oldWidth,
                newWidth: this.gantt.parsedOptions.timelineColWidth,
                scale: oldMillisecondsPerPixel / actualMillisecondsPerPixel,
                oldMillisecondsPerPixel: oldMillisecondsPerPixel,
                newMillisecondsPerPixel: actualMillisecondsPerPixel
            });
        }
    }
}

exports.ZoomScaleManager = ZoomScaleManager;