"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDateDimension = exports.sortTimeFrames = exports.validateTimeFrames = exports.isTimeInterval = exports.getDefaultTimeFrames = exports.timeFrameConfigs = exports.getSqlForTruncatedDate = exports.isWeekDay = exports.WeekDay = void 0;
const dbt_1 = require("../types/dbt");
const errors_1 = require("../types/errors");
const field_1 = require("../types/field");
const timeFrames_1 = require("../types/timeFrames");
var WeekDay;
(function (WeekDay) {
    WeekDay[WeekDay["MONDAY"] = 0] = "MONDAY";
    WeekDay[WeekDay["TUESDAY"] = 1] = "TUESDAY";
    WeekDay[WeekDay["WEDNESDAY"] = 2] = "WEDNESDAY";
    WeekDay[WeekDay["THURSDAY"] = 3] = "THURSDAY";
    WeekDay[WeekDay["FRIDAY"] = 4] = "FRIDAY";
    WeekDay[WeekDay["SATURDAY"] = 5] = "SATURDAY";
    WeekDay[WeekDay["SUNDAY"] = 6] = "SUNDAY";
})(WeekDay || (exports.WeekDay = WeekDay = {}));
const isWeekDay = (value) => Number.isSafeInteger(value) &&
    value >= 0 &&
    value <= 6;
exports.isWeekDay = isWeekDay;
const nullTimeFrameMap = {
    DAY: null,
    DAY_OF_MONTH_NUM: null,
    DAY_OF_WEEK_INDEX: null,
    DAY_OF_WEEK_NAME: null,
    DAY_OF_YEAR_NUM: null,
    HOUR: null,
    MILLISECOND: null,
    MINUTE: null,
    MONTH: null,
    MONTH_NAME: null,
    MONTH_NUM: null,
    QUARTER: null,
    QUARTER_NAME: null,
    QUARTER_NUM: null,
    RAW: null,
    SECOND: null,
    WEEK: null,
    WEEK_NUM: null,
    YEAR: null,
    YEAR_NUM: null,
    HOUR_OF_DAY_NUM: null,
    MINUTE_OF_HOUR_NUM: null,
};
const timeFrameToDatePartMap = {
    ...nullTimeFrameMap,
    [timeFrames_1.TimeFrames.DAY_OF_WEEK_INDEX]: 'DOW',
    [timeFrames_1.TimeFrames.DAY_OF_MONTH_NUM]: 'DAY',
    [timeFrames_1.TimeFrames.DAY_OF_YEAR_NUM]: 'DOY',
    [timeFrames_1.TimeFrames.WEEK_NUM]: 'WEEK',
    [timeFrames_1.TimeFrames.MONTH_NUM]: 'MONTH',
    [timeFrames_1.TimeFrames.QUARTER_NUM]: 'QUARTER',
    [timeFrames_1.TimeFrames.YEAR_NUM]: 'YEAR',
    [timeFrames_1.TimeFrames.HOUR_OF_DAY_NUM]: 'HOUR',
    [timeFrames_1.TimeFrames.MINUTE_OF_HOUR_NUM]: 'MINUTE',
};
const bigqueryStartOfWeekMap = {
    [WeekDay.MONDAY]: 'MONDAY',
    [WeekDay.TUESDAY]: 'TUESDAY',
    [WeekDay.WEDNESDAY]: 'WEDNESDAY',
    [WeekDay.THURSDAY]: 'THURSDAY',
    [WeekDay.FRIDAY]: 'FRIDAY',
    [WeekDay.SATURDAY]: 'SATURDAY',
    [WeekDay.SUNDAY]: 'SUNDAY',
};
const bigqueryConfig = {
    getSqlForTruncatedDate: (timeFrame, originalSql, type, startOfWeek) => {
        const datePart = timeFrame === timeFrames_1.TimeFrames.WEEK && (0, exports.isWeekDay)(startOfWeek)
            ? `${timeFrame}(${bigqueryStartOfWeekMap[startOfWeek]})`
            : timeFrame;
        if (type === field_1.DimensionType.TIMESTAMP) {
            return `TIMESTAMP_TRUNC(${originalSql}, ${datePart})`;
        }
        return `DATE_TRUNC(${originalSql}, ${datePart})`;
    },
    getSqlForDatePart: (timeFrame, originalSql, _, startOfWeek) => {
        const bigqueryTimeFrameExpressions = {
            ...timeFrameToDatePartMap,
            [timeFrames_1.TimeFrames.DAY_OF_WEEK_INDEX]: 'DAYOFWEEK',
            [timeFrames_1.TimeFrames.DAY_OF_YEAR_NUM]: 'DAYOFYEAR',
        };
        const datePart = bigqueryTimeFrameExpressions[timeFrame];
        if (!datePart) {
            throw new errors_1.ParseError(`Cannot recognise date part for ${timeFrame}`);
        }
        if (timeFrame === timeFrames_1.TimeFrames.WEEK_NUM && (0, exports.isWeekDay)(startOfWeek)) {
            return `EXTRACT(${datePart}(${bigqueryStartOfWeekMap[startOfWeek]}) FROM ${originalSql})`;
        }
        return `EXTRACT(${datePart} FROM ${originalSql})`;
    },
    getSqlForDatePartName: (timeFrame, originalSql, type) => {
        // https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#format_elements_date_time
        const timeFrameExpressions = {
            ...nullTimeFrameMap,
            [timeFrames_1.TimeFrames.DAY_OF_WEEK_NAME]: '%A',
            [timeFrames_1.TimeFrames.MONTH_NAME]: '%B',
            [timeFrames_1.TimeFrames.QUARTER_NAME]: 'Q%Q',
        };
        const formatExpression = timeFrameExpressions[timeFrame];
        if (!formatExpression) {
            throw new errors_1.ParseError(`Cannot recognise format expression for ${timeFrame}`);
        }
        if (type === field_1.DimensionType.TIMESTAMP) {
            return `FORMAT_DATETIME('${formatExpression}', ${originalSql})`;
        }
        return `FORMAT_DATE('${formatExpression}', ${originalSql})`;
    },
};
// Snowflake handles start of week by setting a session variable (WEEK_START)
const snowflakeConfig = {
    getSqlForTruncatedDate: (timeFrame, originalSql) => `DATE_TRUNC('${timeFrame}', ${originalSql})`,
    getSqlForDatePart: (timeFrame, originalSql) => {
        const datePart = timeFrameToDatePartMap[timeFrame];
        if (!datePart) {
            throw new errors_1.ParseError(`Cannot recognise date part for ${timeFrame}`);
        }
        return `DATE_PART('${datePart}', ${originalSql})`;
    },
    getSqlForDatePartName: (timeFrame, originalSql) => {
        // https://docs.snowflake.com/en/sql-reference/functions/to_char.html
        const timeFrameExpressionsFn = {
            ...nullTimeFrameMap,
            [timeFrames_1.TimeFrames.DAY_OF_WEEK_NAME]: () => `DECODE(TO_CHAR(${originalSql}, 'DY'), 'Mon', 'Monday', 'Tue', 'Tuesday', 'Wed', 'Wednesday', 'Thu', 'Thursday', 'Fri', 'Friday', 'Sat', 'Saturday', 'Sun', 'Sunday')`,
            [timeFrames_1.TimeFrames.MONTH_NAME]: () => `TO_CHAR(${originalSql}, 'MMMM')`,
            [timeFrames_1.TimeFrames.QUARTER_NAME]: () => `CONCAT('Q', DATE_PART('QUARTER', ${originalSql}))`,
        };
        const formatExpressionFn = timeFrameExpressionsFn[timeFrame];
        if (!formatExpressionFn) {
            throw new errors_1.ParseError(`Cannot recognise format expression for ${timeFrame}`);
        }
        return formatExpressionFn();
    },
};
const postgresConfig = {
    getSqlForTruncatedDate: (timeFrame, originalSql, _, startOfWeek) => {
        if (timeFrame === timeFrames_1.TimeFrames.WEEK && (0, exports.isWeekDay)(startOfWeek)) {
            const intervalDiff = `${startOfWeek} days`;
            return `(DATE_TRUNC('${timeFrame}', (${originalSql} - interval '${intervalDiff}')) + interval '${intervalDiff}')`;
        }
        return `DATE_TRUNC('${timeFrame}', ${originalSql})`;
    },
    getSqlForDatePart: (timeFrame, originalSql, _, startOfWeek) => {
        const datePart = timeFrameToDatePartMap[timeFrame];
        if (!datePart) {
            throw new errors_1.ParseError(`Cannot recognise date part for ${timeFrame}`);
        }
        if (timeFrame === timeFrames_1.TimeFrames.WEEK_NUM && (0, exports.isWeekDay)(startOfWeek)) {
            const intervalDiff = `${startOfWeek} days`;
            return `DATE_PART('${datePart}', (${originalSql} - interval '${intervalDiff}'))`;
        }
        return `DATE_PART('${datePart}', ${originalSql})`;
    },
    getSqlForDatePartName: (timeFrame, originalSql) => {
        // https://www.postgresql.org/docs/current/functions-formatting.html
        const timeFrameExpressions = {
            ...nullTimeFrameMap,
            [timeFrames_1.TimeFrames.DAY_OF_WEEK_NAME]: 'Day',
            [timeFrames_1.TimeFrames.MONTH_NAME]: 'Month',
            [timeFrames_1.TimeFrames.QUARTER_NAME]: '"Q"Q',
        };
        const formatExpression = timeFrameExpressions[timeFrame];
        if (!formatExpression) {
            throw new errors_1.ParseError(`Cannot recognise format expression for ${timeFrame}`);
        }
        return `TO_CHAR(${originalSql}, 'FM${formatExpression}')`;
    },
};
const databricksConfig = {
    getSqlForTruncatedDate: (timeFrame, originalSql, _, startOfWeek) => {
        if (timeFrame === timeFrames_1.TimeFrames.WEEK && (0, exports.isWeekDay)(startOfWeek)) {
            const intervalDiff = `${startOfWeek}`;
            return `DATEADD(DAY, ${intervalDiff}, DATE_TRUNC('${timeFrame}', DATEADD(DAY, -${intervalDiff}, ${originalSql})))`;
        }
        return `DATE_TRUNC('${timeFrame}', ${originalSql})`;
    },
    getSqlForDatePart: (timeFrame, originalSql, _, startOfWeek) => {
        const datePart = timeFrameToDatePartMap[timeFrame];
        if (!datePart) {
            throw new errors_1.ParseError(`Cannot recognise date part for ${timeFrame}`);
        }
        if (timeFrame === timeFrames_1.TimeFrames.WEEK_NUM && (0, exports.isWeekDay)(startOfWeek)) {
            const intervalDiff = `${startOfWeek} days`;
            return `DATE_PART('${datePart}', (${originalSql} - interval '${intervalDiff}'))`;
        }
        return `DATE_PART('${datePart}', ${originalSql})`;
    },
    getSqlForDatePartName: (timeFrame, originalSql) => {
        // https://docs.databricks.com/spark/latest/spark-sql/language-manual/functions/date_format.html
        const timeFrameExpressions = {
            ...nullTimeFrameMap,
            [timeFrames_1.TimeFrames.DAY_OF_WEEK_NAME]: 'EEEE',
            [timeFrames_1.TimeFrames.MONTH_NAME]: 'MMMM',
            [timeFrames_1.TimeFrames.QUARTER_NAME]: 'QQQ',
        };
        const formatExpression = timeFrameExpressions[timeFrame];
        if (!formatExpression) {
            throw new errors_1.ParseError(`Cannot recognise format expression for ${timeFrame}`);
        }
        return `DATE_FORMAT(${originalSql}, '${formatExpression}')`;
    },
};
const trinoConfig = {
    getSqlForTruncatedDate: (timeFrame, originalSql, _, startOfWeek) => {
        if (timeFrame === timeFrames_1.TimeFrames.WEEK && (0, exports.isWeekDay)(startOfWeek)) {
            const intervalDiff = `'${startOfWeek}' day`;
            return `(DATE_TRUNC('${timeFrame}', (${originalSql} - interval ${intervalDiff})) + interval ${intervalDiff})`;
        }
        return `DATE_TRUNC('${timeFrame}', ${originalSql})`;
    },
    getSqlForDatePart: (timeFrame, originalSql, _, startOfWeek) => {
        const datePart = timeFrameToDatePartMap[timeFrame];
        if (!datePart) {
            throw new errors_1.ParseError(`Cannot recognise date part for ${timeFrame}`);
        }
        if (timeFrame === timeFrames_1.TimeFrames.WEEK_NUM && (0, exports.isWeekDay)(startOfWeek)) {
            const intervalDiff = `'${startOfWeek}' day`;
            return `EXTRACT(${datePart} FROM (${originalSql} - interval ${intervalDiff}))`;
        }
        return `EXTRACT(${datePart} FROM ${originalSql})`;
    },
    getSqlForDatePartName: (timeFrame, originalSql) => {
        const timeFrameExpressionsFn = {
            ...nullTimeFrameMap,
            [timeFrames_1.TimeFrames.DAY_OF_WEEK_NAME]: () => `date_format(${originalSql}, '%W')`,
            [timeFrames_1.TimeFrames.MONTH_NAME]: () => `date_format(${originalSql}, '%M')`,
            [timeFrames_1.TimeFrames.QUARTER_NAME]: () => `CONCAT('Q', cast(extract(QUARTER from ${originalSql}) as varchar))`,
        };
        const formatExpressionFn = timeFrameExpressionsFn[timeFrame];
        if (!formatExpressionFn) {
            throw new errors_1.ParseError(`Cannot recognise format expression for ${timeFrame}`);
        }
        return formatExpressionFn();
    },
};
const clickhouseConfig = {
    getSqlForTruncatedDate: (timeFrame, originalSql, _, startOfWeek) => {
        if (timeFrame === timeFrames_1.TimeFrames.WEEK && (0, exports.isWeekDay)(startOfWeek)) {
            const intervalDiff = startOfWeek;
            return `addDays(toStartOfWeek(addDays(${originalSql}, -${intervalDiff})), ${intervalDiff})`;
        }
        switch (timeFrame) {
            case timeFrames_1.TimeFrames.DAY:
                return `toStartOfDay(${originalSql})`;
            case timeFrames_1.TimeFrames.WEEK:
                return `toStartOfWeek(${originalSql})`;
            case timeFrames_1.TimeFrames.MONTH:
                return `toStartOfMonth(${originalSql})`;
            case timeFrames_1.TimeFrames.QUARTER:
                return `toStartOfQuarter(${originalSql})`;
            case timeFrames_1.TimeFrames.YEAR:
                return `toStartOfYear(${originalSql})`;
            case timeFrames_1.TimeFrames.HOUR:
                return `toStartOfHour(${originalSql})`;
            case timeFrames_1.TimeFrames.MINUTE:
                return `toStartOfMinute(${originalSql})`;
            default:
                throw new errors_1.ParseError(`Cannot recognise truncate function for ${timeFrame}`);
        }
    },
    getSqlForDatePart: (timeFrame, originalSql) => {
        const clickhouseTimeFrameMap = {
            ...timeFrameToDatePartMap,
            [timeFrames_1.TimeFrames.DAY_OF_WEEK_INDEX]: 'toDayOfWeek',
            [timeFrames_1.TimeFrames.DAY_OF_MONTH_NUM]: 'toDayOfMonth',
            [timeFrames_1.TimeFrames.DAY_OF_YEAR_NUM]: 'toDayOfYear',
            [timeFrames_1.TimeFrames.WEEK_NUM]: 'toWeek',
            [timeFrames_1.TimeFrames.MONTH_NUM]: 'toMonth',
            [timeFrames_1.TimeFrames.QUARTER_NUM]: 'toQuarter',
            [timeFrames_1.TimeFrames.YEAR_NUM]: 'toYear',
            [timeFrames_1.TimeFrames.HOUR_OF_DAY_NUM]: 'toHour',
            [timeFrames_1.TimeFrames.MINUTE_OF_HOUR_NUM]: 'toMinute',
        };
        const extractFunction = clickhouseTimeFrameMap[timeFrame];
        if (!extractFunction) {
            throw new errors_1.ParseError(`Cannot recognise extract function for ${timeFrame}`);
        }
        return `${extractFunction}(${originalSql})`;
    },
    getSqlForDatePartName: (timeFrame, originalSql) => {
        const timeFrameExpressions = {
            ...nullTimeFrameMap,
            [timeFrames_1.TimeFrames.DAY_OF_WEEK_NAME]: 'toDayOfWeekName',
            [timeFrames_1.TimeFrames.MONTH_NAME]: 'toMonthName',
            [timeFrames_1.TimeFrames.QUARTER_NAME]: `concat('Q', toString(toQuarter(${originalSql})))`,
        };
        const formatExpression = timeFrameExpressions[timeFrame];
        if (!formatExpression) {
            throw new errors_1.ParseError(`Cannot recognise format expression for ${timeFrame}`);
        }
        if (timeFrame === timeFrames_1.TimeFrames.QUARTER_NAME) {
            return formatExpression;
        }
        return `${formatExpression}(${originalSql})`;
    },
};
const warehouseConfigs = {
    [dbt_1.SupportedDbtAdapter.BIGQUERY]: bigqueryConfig,
    [dbt_1.SupportedDbtAdapter.SNOWFLAKE]: snowflakeConfig,
    [dbt_1.SupportedDbtAdapter.REDSHIFT]: postgresConfig,
    [dbt_1.SupportedDbtAdapter.POSTGRES]: postgresConfig,
    [dbt_1.SupportedDbtAdapter.DATABRICKS]: databricksConfig,
    [dbt_1.SupportedDbtAdapter.TRINO]: trinoConfig,
    [dbt_1.SupportedDbtAdapter.CLICKHOUSE]: clickhouseConfig,
};
const getSqlForTruncatedDate = (adapterType, timeFrame, originalSql, type, startOfWeek) => warehouseConfigs[adapterType].getSqlForTruncatedDate(timeFrame, originalSql, type, startOfWeek);
exports.getSqlForTruncatedDate = getSqlForTruncatedDate;
const getSqlForDatePart = (adapterType, timeFrame, originalSql, type, startOfWeek) => warehouseConfigs[adapterType].getSqlForDatePart(timeFrame, originalSql, type, startOfWeek);
const getSqlForDatePartName = (adapterType, timeFrame, originalSql, type) => warehouseConfigs[adapterType].getSqlForDatePartName(timeFrame, originalSql, type);
exports.timeFrameConfigs = {
    RAW: {
        getLabel: () => 'Raw',
        getDimensionType: (fallback) => fallback,
        getSql: (_adapterType, _timeInterval, originalSql) => originalSql,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    MILLISECOND: {
        getLabel: () => 'Millisecond',
        getDimensionType: () => field_1.DimensionType.TIMESTAMP,
        getSql: exports.getSqlForTruncatedDate,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    SECOND: {
        getLabel: () => 'Second',
        getDimensionType: () => field_1.DimensionType.TIMESTAMP,
        getSql: exports.getSqlForTruncatedDate,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    MINUTE: {
        getLabel: () => 'Minute',
        getDimensionType: () => field_1.DimensionType.TIMESTAMP,
        getSql: exports.getSqlForTruncatedDate,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    HOUR: {
        getLabel: () => 'Hour',
        getDimensionType: () => field_1.DimensionType.TIMESTAMP,
        getSql: exports.getSqlForTruncatedDate,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    DAY: {
        getLabel: () => 'Day',
        getDimensionType: () => field_1.DimensionType.DATE,
        getSql: exports.getSqlForTruncatedDate,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => ({
            year: '{bold|{yyyy}}',
            month: '{bold|{MMM}}',
            day: '{d}',
            hour: '',
        }),
    },
    WEEK: {
        getLabel: () => 'Week',
        getDimensionType: () => field_1.DimensionType.DATE,
        getSql: exports.getSqlForTruncatedDate,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    MONTH: {
        getLabel: () => 'Month',
        getDimensionType: () => field_1.DimensionType.DATE,
        getSql: exports.getSqlForTruncatedDate,
        getAxisMinInterval: () => 2629800000,
        getAxisLabelFormatter: () => null,
    },
    QUARTER: {
        getLabel: () => 'Quarter',
        getDimensionType: () => field_1.DimensionType.DATE,
        getSql: exports.getSqlForTruncatedDate,
        getAxisMinInterval: () => 7889400000,
        getAxisLabelFormatter: () => null,
    },
    YEAR: {
        getLabel: () => 'Year',
        getDimensionType: () => field_1.DimensionType.DATE,
        getSql: exports.getSqlForTruncatedDate,
        getAxisMinInterval: () => 31557600000,
        getAxisLabelFormatter: () => null,
    },
    WEEK_NUM: {
        getLabel: () => 'Week (number)',
        getDimensionType: () => field_1.DimensionType.NUMBER,
        getSql: getSqlForDatePart,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    MONTH_NUM: {
        getLabel: () => 'Month (number)',
        getDimensionType: () => field_1.DimensionType.NUMBER,
        getSql: getSqlForDatePart,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    DAY_OF_WEEK_INDEX: {
        getLabel: () => 'Day of the week (index)',
        getDimensionType: () => field_1.DimensionType.NUMBER,
        getSql: getSqlForDatePart,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    DAY_OF_MONTH_NUM: {
        getLabel: () => 'Day of the month (number)',
        getDimensionType: () => field_1.DimensionType.NUMBER,
        getSql: getSqlForDatePart,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    DAY_OF_YEAR_NUM: {
        getLabel: () => 'Day of the year (number)',
        getDimensionType: () => field_1.DimensionType.NUMBER,
        getSql: getSqlForDatePart,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    QUARTER_NUM: {
        getLabel: () => 'Quarter (number)',
        getDimensionType: () => field_1.DimensionType.NUMBER,
        getSql: getSqlForDatePart,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    YEAR_NUM: {
        getLabel: () => 'Year (number)',
        getDimensionType: () => field_1.DimensionType.NUMBER,
        getSql: getSqlForDatePart,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    DAY_OF_WEEK_NAME: {
        getLabel: () => 'Day of the week (name)',
        getDimensionType: () => field_1.DimensionType.STRING,
        getSql: getSqlForDatePartName,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    MONTH_NAME: {
        getLabel: () => 'Month (name)',
        getDimensionType: () => field_1.DimensionType.STRING,
        getSql: getSqlForDatePartName,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    QUARTER_NAME: {
        getLabel: () => 'Quarter (name)',
        getDimensionType: () => field_1.DimensionType.STRING,
        getSql: getSqlForDatePartName,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    HOUR_OF_DAY_NUM: {
        getLabel: () => 'Hour of day (number)',
        getDimensionType: () => field_1.DimensionType.NUMBER,
        getSql: getSqlForDatePart,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
    MINUTE_OF_HOUR_NUM: {
        getLabel: () => 'Minute of hour (number)',
        getDimensionType: () => field_1.DimensionType.NUMBER,
        getSql: getSqlForDatePart,
        getAxisMinInterval: () => null,
        getAxisLabelFormatter: () => null,
    },
};
const getDefaultTimeFrames = (type) => type === field_1.DimensionType.TIMESTAMP
    ? [
        timeFrames_1.TimeFrames.RAW,
        timeFrames_1.TimeFrames.DAY,
        timeFrames_1.TimeFrames.WEEK,
        timeFrames_1.TimeFrames.MONTH,
        timeFrames_1.TimeFrames.QUARTER,
        timeFrames_1.TimeFrames.YEAR,
    ]
    : [
        timeFrames_1.TimeFrames.DAY,
        timeFrames_1.TimeFrames.WEEK,
        timeFrames_1.TimeFrames.MONTH,
        timeFrames_1.TimeFrames.QUARTER,
        timeFrames_1.TimeFrames.YEAR,
    ];
exports.getDefaultTimeFrames = getDefaultTimeFrames;
const isTimeInterval = (value) => Object.keys(exports.timeFrameConfigs).includes(value);
exports.isTimeInterval = isTimeInterval;
const validateTimeFrames = (values) => values.reduce((acc, value) => {
    const uppercaseValue = value.toUpperCase();
    return (0, exports.isTimeInterval)(uppercaseValue) ? [...acc, uppercaseValue] : acc;
}, []);
exports.validateTimeFrames = validateTimeFrames;
const timeFrameOrder = [
    undefined,
    timeFrames_1.TimeFrames.RAW,
    timeFrames_1.TimeFrames.MILLISECOND,
    timeFrames_1.TimeFrames.SECOND,
    timeFrames_1.TimeFrames.MINUTE,
    timeFrames_1.TimeFrames.HOUR,
    timeFrames_1.TimeFrames.DAY,
    timeFrames_1.TimeFrames.DAY_OF_WEEK_INDEX,
    timeFrames_1.TimeFrames.DAY_OF_WEEK_NAME,
    timeFrames_1.TimeFrames.DAY_OF_MONTH_NUM,
    timeFrames_1.TimeFrames.DAY_OF_YEAR_NUM,
    timeFrames_1.TimeFrames.WEEK,
    timeFrames_1.TimeFrames.WEEK_NUM,
    timeFrames_1.TimeFrames.MONTH,
    timeFrames_1.TimeFrames.MONTH_NUM,
    timeFrames_1.TimeFrames.MONTH_NAME,
    timeFrames_1.TimeFrames.QUARTER,
    timeFrames_1.TimeFrames.QUARTER_NUM,
    timeFrames_1.TimeFrames.QUARTER_NAME,
    timeFrames_1.TimeFrames.YEAR,
    timeFrames_1.TimeFrames.YEAR_NUM,
    timeFrames_1.TimeFrames.HOUR_OF_DAY_NUM,
    timeFrames_1.TimeFrames.MINUTE_OF_HOUR_NUM,
];
const sortTimeFrames = (a, b) => timeFrameOrder.indexOf(a) - timeFrameOrder.indexOf(b);
exports.sortTimeFrames = sortTimeFrames;
const getDateDimension = (dimensionId) => {
    const timeFrames = Object.values(timeFrames_1.DateGranularity).map((tf) => tf.toLowerCase());
    const isDate = timeFrames.some((timeFrame) => dimensionId.endsWith(timeFrame));
    if (isDate) {
        const regex = new RegExp(`_(${timeFrames.join('|')})$`);
        const baseDimensionId = dimensionId.replace(regex, '');
        const timeString = dimensionId.replace(`${baseDimensionId}_`, '');
        const [newTimeFrame] = (0, exports.validateTimeFrames)([timeString]);
        if (baseDimensionId && newTimeFrame)
            return {
                baseDimensionId,
                newTimeFrame,
            };
    }
    return {};
};
exports.getDateDimension = getDateDimension;
//# sourceMappingURL=timeFrames.js.map