import { formatAddress, parseCellAddress } from '@bilig/formula';
const TRUSTED_TRACKED_PHYSICAL_SHEET_ID_PROPERTY = '__biligTrackedPhysicalSheetId';
const TRUSTED_TRACKED_PHYSICAL_SORTED_SPLIT_PROPERTY = '__biligTrackedPhysicalSortedSliceSplit';
export function reverseUint32Array(values) {
    const reversed = new Uint32Array(values.length);
    for (let index = 0; index < values.length; index += 1) {
        reversed[index] = values[values.length - 1 - index];
    }
    return reversed;
}
export function reverseUint32ArrayInPlace(values) {
    let left = 0;
    let right = values.length - 1;
    while (left < right) {
        const nextLeft = values[right];
        values[right] = values[left];
        values[left] = nextLeft;
        left += 1;
        right -= 1;
    }
    return values;
}
export function mutationErrorMessage(message, cause) {
    return cause instanceof Error && cause.message.length > 0 ? cause.message : message;
}
export function assertNever(value) {
    throw new Error(`Unexpected value: ${String(value)}`);
}
export function normalizeRange(range) {
    const start = parseCellAddress(range.startAddress, range.sheetName);
    const end = parseCellAddress(range.endAddress, range.sheetName);
    const startRow = Math.min(start.row, end.row);
    const endRow = Math.max(start.row, end.row);
    const startCol = Math.min(start.col, end.col);
    const endCol = Math.max(start.col, end.col);
    return {
        ...range,
        startAddress: formatAddress(startRow, startCol),
        endAddress: formatAddress(endRow, endCol),
        startRow,
        endRow,
        startCol,
        endCol,
    };
}
export function rangesIntersect(left, right) {
    const a = normalizeRange(left);
    const b = normalizeRange(right);
    return !(a.sheetName !== b.sheetName || a.endRow < b.startRow || b.endRow < a.startRow || a.endCol < b.startCol || b.endCol < a.startCol);
}
export function cellRange(sheetName, address) {
    return {
        sheetName,
        startAddress: address,
        endAddress: address,
    };
}
export function throwProtectionBlocked(message) {
    throw new Error(`Workbook protection blocks this change: ${message}`);
}
export function mergeChangedCellIndices(base, extras) {
    if (base.length === 0) {
        return extras instanceof Uint32Array ? extras : Uint32Array.from(extras);
    }
    if (extras.length === 0) {
        return base instanceof Uint32Array ? base : Uint32Array.from(base);
    }
    if (base.length === 1 && extras.length === 1) {
        const baseCellIndex = base[0];
        const extraCellIndex = extras[0];
        return baseCellIndex === extraCellIndex ? Uint32Array.of(baseCellIndex) : Uint32Array.of(baseCellIndex, extraCellIndex);
    }
    if (base.length === 1) {
        return mergeSingleBaseChangedCellIndex(base[0], extras);
    }
    if (extras.length === 1) {
        return mergeSingleExtraChangedCellIndex(base, extras[0]);
    }
    const merged = new Set();
    for (let index = 0; index < base.length; index += 1) {
        merged.add(base[index]);
    }
    for (let index = 0; index < extras.length; index += 1) {
        merged.add(extras[index]);
    }
    return Uint32Array.from(merged);
}
function mergeSingleBaseChangedCellIndex(baseCellIndex, extras) {
    let duplicateIndex = -1;
    for (let index = 0; index < extras.length; index += 1) {
        if (extras[index] === baseCellIndex) {
            duplicateIndex = index;
            break;
        }
    }
    const merged = new Uint32Array(duplicateIndex === -1 ? extras.length + 1 : extras.length);
    merged[0] = baseCellIndex;
    let writeIndex = 1;
    for (let index = 0; index < extras.length; index += 1) {
        if (index === duplicateIndex) {
            continue;
        }
        merged[writeIndex] = extras[index];
        writeIndex += 1;
    }
    return merged;
}
function mergeSingleExtraChangedCellIndex(base, extraCellIndex) {
    for (let index = 0; index < base.length; index += 1) {
        if (base[index] === extraCellIndex) {
            return base instanceof Uint32Array ? base : Uint32Array.from(base);
        }
    }
    const merged = new Uint32Array(base.length + 1);
    for (let index = 0; index < base.length; index += 1) {
        merged[index] = base[index];
    }
    merged[base.length] = extraCellIndex;
    return merged;
}
export function tagTrustedPhysicalTrackedChanges(changed, sheetId, sortedSliceSplit) {
    Reflect.set(changed, TRUSTED_TRACKED_PHYSICAL_SHEET_ID_PROPERTY, sheetId);
    Reflect.set(changed, TRUSTED_TRACKED_PHYSICAL_SORTED_SPLIT_PROPERTY, sortedSliceSplit);
}
export function canTrustPhysicalTrackedChangeSplit(changed, sheetId, split, workbook) {
    if (split <= 0 || split >= changed.length) {
        return false;
    }
    const sheet = workbook.getSheetById(sheetId);
    if (!sheet || sheet.structureVersion !== 1) {
        return false;
    }
    const cellStore = workbook.cellStore;
    const validateSlice = (start, end) => {
        let previousRow = -1;
        let previousCol = -1;
        for (let index = start; index < end; index += 1) {
            const cellIndex = changed[index];
            if (cellStore.sheetIds[cellIndex] !== sheetId) {
                return false;
            }
            const row = cellStore.rows[cellIndex];
            const col = cellStore.cols[cellIndex];
            if (row === undefined || col === undefined || row < previousRow || (row === previousRow && col <= previousCol)) {
                return false;
            }
            previousRow = row;
            previousCol = col;
        }
        return true;
    };
    return validateSlice(0, split) && validateSlice(split, changed.length);
}
export function makeExistingNumericMutationResult(changedCellIndices, explicitChangedCount) {
    return { changedCellIndices, explicitChangedCount };
}
export function makeCompactExistingNumericMutationResult(firstChangedCellIndex, secondChangedCellIndex, explicitChangedCount, secondChangedNumericValue, secondChangedRow, secondChangedCol, secondChangedValue) {
    if (secondChangedCellIndex === undefined) {
        return { firstChangedCellIndex, changedCellCount: 1, explicitChangedCount };
    }
    const result = {
        firstChangedCellIndex,
        secondChangedCellIndex,
        changedCellCount: 2,
        explicitChangedCount,
    };
    if (secondChangedNumericValue !== undefined) {
        result.secondChangedNumericValue = secondChangedNumericValue;
    }
    if (secondChangedValue !== undefined) {
        result.secondChangedValue = secondChangedValue;
    }
    if (typeof secondChangedRow === 'object') {
        result.secondChangedRow = secondChangedRow.row;
        result.secondChangedCol = secondChangedRow.col;
    }
    else if (secondChangedRow !== undefined && secondChangedCol !== undefined) {
        result.secondChangedRow = secondChangedRow;
        result.secondChangedCol = secondChangedCol;
    }
    return result;
}
//# sourceMappingURL=operation-change-helpers.js.map