export class FormulaReferenceAdjustor {
    static parseCellReference(ref) {
        const match = ref.match(this.SINGLE_CELL_REGEX);
        if (!match) return null;
        const [, colAbsolute, colStr, rowAbsolute, rowStr] = match;
        let type;
        return type = colAbsolute && rowAbsolute ? "absolute" : colAbsolute && !rowAbsolute ? "mixed_col" : !colAbsolute && rowAbsolute ? "mixed_row" : "relative", 
        {
            type: type,
            col: this.columnToNumber(colStr),
            row: parseInt(rowStr, 10) - 1,
            originalColRef: colAbsolute + colStr,
            originalRowRef: rowAbsolute + rowStr,
            fullReference: ref
        };
    }
    static columnToNumber(col) {
        let result = 0;
        for (let i = 0; i < col.length; i++) result = 26 * result + (col.charCodeAt(i) - "A".charCodeAt(0) + 1);
        return result - 1;
    }
    static numberToColumn(num) {
        let result = "", n = num + 1;
        for (;n > 0; ) n--, result = String.fromCharCode("A".charCodeAt(0) + n % 26) + result, 
        n = Math.floor(n / 26);
        return result;
    }
    static adjustCellReference(ref, offset) {
        let newCol = ref.col, newRow = ref.row;
        switch (ref.type) {
          case "relative":
            newCol += offset.colOffset, newRow += offset.rowOffset;
            break;

          case "mixed_row":
            newCol += offset.colOffset, newRow = ref.row;
            break;

          case "mixed_col":
            newCol = ref.col, newRow += offset.rowOffset;
            break;

          case "absolute":
            newCol = ref.col, newRow = ref.row;
        }
        newCol < 0 && (newCol = 0), newRow < 0 && (newRow = 0);
        let result = "";
        return "absolute" !== ref.type && "mixed_col" !== ref.type || (result += "$"), result += this.numberToColumn(newCol), 
        "absolute" !== ref.type && "mixed_row" !== ref.type || (result += "$"), result += newRow + 1, 
        result;
    }
    static adjustFormulaReferences(formula, colOffset, rowOffset) {
        const offset = {
            colOffset: colOffset,
            rowOffset: rowOffset
        };
        return "string" == typeof formula ? formula.replace(this.CELL_REF_REGEX, (match => {
            if (match.includes(":")) {
                const parts = match.split(":"), startRef = this.parseCellReference(parts[0]), endRef = this.parseCellReference(parts[1]);
                if (startRef && endRef) {
                    return `${this.adjustCellReference(startRef, offset)}:${this.adjustCellReference(endRef, offset)}`;
                }
                return match;
            }
            const ref = this.parseCellReference(match);
            return ref ? this.adjustCellReference(ref, offset) : match;
        })) : formula;
    }
    static isFormula(value) {
        return "string" == typeof value && value.startsWith("=");
    }
    static extractReferences(formula) {
        const references = [], matches = formula.match(this.CELL_REF_REGEX);
        return matches && matches.forEach((match => {
            if (match.includes(":")) {
                const parts = match.split(":"), startRef = this.parseCellReference(parts[0]), endRef = this.parseCellReference(parts[1]);
                startRef && references.push(startRef), endRef && references.push(endRef);
            } else {
                const ref = this.parseCellReference(match);
                ref && references.push(ref);
            }
        })), references;
    }
    static getFormulaReferenceBounds(formula) {
        const references = this.extractReferences(formula);
        if (0 === references.length) return null;
        let minCol = 1 / 0, maxCol = -1 / 0, minRow = 1 / 0, maxRow = -1 / 0;
        return references.forEach((ref => {
            minCol = Math.min(minCol, ref.col), maxCol = Math.max(maxCol, ref.col), minRow = Math.min(minRow, ref.row), 
            maxRow = Math.max(maxRow, ref.row);
        })), {
            minCol: minCol,
            maxCol: maxCol,
            minRow: minRow,
            maxRow: maxRow
        };
    }
}

FormulaReferenceAdjustor.CELL_REF_REGEX = /(\$?[A-Z]+\$?\d+(?::\$?[A-Z]+\$?\d+)?)/gi, 
FormulaReferenceAdjustor.SINGLE_CELL_REGEX = /(\$?)([A-Z]+)(\$?)(\d+)/i;
//# sourceMappingURL=formula-reference-adjustor.js.map