{
  "version": 3,
  "sources": ["../../../../src/core/managers/table-manager.ts"],
  "sourcesContent": [
    "import type {\n  CellAddress,\n  SerializedCellValue,\n  SpreadsheetRange,\n  SpreadsheetRangeEnd,\n  TableDefinition,\n} from \"../types.cjs\";\nimport type { TableManagerSnapshot } from \"../engine-snapshot.cjs\";\nimport {\n  checkRangeIntersection,\n  getCellReference,\n  parseCellReference,\n} from \"../utils.cjs\";\nimport type { WorkbookManager } from \"./workbook-manager.cjs\";\n\nexport class TableManager {\n  tables: Map<\n    /**\n     * workbook name -> table name -> table definition\n     */\n    string,\n    Map<string, TableDefinition>\n  > = new Map();\n  private workbookManager: WorkbookManager;\n\n  constructor(workbookManager: WorkbookManager) {\n    this.workbookManager = workbookManager;\n  }\n\n  getTables(workbookName: string): Map<string, TableDefinition> {\n    return this.tables.get(workbookName) ?? new Map();\n  }\n\n  getTable(opts: {\n    workbookName: string;\n    name: string;\n  }): TableDefinition | undefined {\n    return this.tables.get(opts.workbookName)?.get(opts.name);\n  }\n\n  makeTable({\n    tableName,\n    sheetName,\n    workbookName,\n    start,\n    numRows,\n    numCols,\n    getCellValue,\n  }: {\n    tableName: string;\n    sheetName: string;\n    start: string;\n    numRows: SpreadsheetRangeEnd;\n    numCols: number;\n    workbookName: string;\n    getCellValue: (cellAddress: CellAddress) => SerializedCellValue;\n  }): TableDefinition {\n    const { rowIndex, colIndex } = parseCellReference(start);\n\n    const headers = new Map<string, { name: string; index: number }>();\n    for (let i = 0; i < numCols; i++) {\n      const header = getCellValue({\n        rowIndex,\n        colIndex: colIndex + i,\n        sheetName,\n        workbookName,\n      });\n\n      if (header) {\n        headers.set(String(header), { name: String(header), index: i });\n      } else {\n        headers.set(`Column ${i + 1}`, { name: `Column ${i + 1}`, index: i });\n      }\n    }\n\n    const endRow: SpreadsheetRangeEnd =\n      numRows.type === \"number\"\n        ? { type: \"number\", value: rowIndex + numRows.value }\n        : numRows;\n\n    const table: TableDefinition = {\n      name: tableName,\n      sheetName,\n      workbookName,\n      start: {\n        rowIndex,\n        colIndex,\n      },\n      headers,\n      endRow,\n    };\n\n    return table;\n  }\n\n  copyTable(\n    from: {\n      workbookName: string;\n      tableName: string;\n    },\n    to: {\n      workbookName: string;\n      tableName: string;\n    },\n  ): void {\n    const fromTable = this.getTable({\n      workbookName: from.workbookName,\n      name: from.tableName,\n    });\n    if (!fromTable) {\n      throw new Error(\"Table not found\");\n    }\n    const wb = this.tables.get(to.workbookName);\n    if (!wb) {\n      throw new Error(\"Workbook not found\");\n    }\n    const newTable: TableDefinition = {\n      ...fromTable,\n      workbookName: to.workbookName,\n    };\n    wb.set(to.tableName, newTable);\n  }\n\n  addTable(props: {\n    tableName: string;\n    sheetName: string;\n    start: string;\n    numRows: SpreadsheetRangeEnd;\n    numCols: number;\n    workbookName: string;\n    getCellValue: (cellAddress: CellAddress) => SerializedCellValue;\n  }): TableDefinition {\n    const tableName = props.tableName;\n    const table = this.makeTable(props);\n\n    let wb = this.tables.get(props.workbookName);\n    if (!wb) {\n      wb = new Map();\n      this.tables.set(props.workbookName, wb);\n    }\n\n    wb.set(tableName, table);\n\n    return table;\n  }\n\n  renameTable(\n    workbookName: string,\n    names: { oldName: string; newName: string },\n  ): void {\n    const wb = this.tables.get(workbookName);\n    if (!wb) {\n      throw new Error(\"Workbook not found\");\n    }\n    const table = wb.get(names.oldName);\n    if (!table) {\n      throw new Error(\"Table not found\");\n    }\n    table.name = names.newName;\n    wb.set(names.newName, table);\n    wb.delete(names.oldName);\n  }\n\n  updateTable({\n    tableName,\n    sheetName,\n    start,\n    numRows,\n    numCols,\n    workbookName,\n    getCellValue,\n  }: {\n    tableName: string;\n    sheetName?: string;\n    start?: string;\n    numRows?: SpreadsheetRangeEnd;\n    workbookName: string;\n    numCols?: number;\n    getCellValue: (cellAddress: CellAddress) => SerializedCellValue;\n  }): void {\n    const wb = this.tables.get(workbookName);\n    if (!wb) {\n      throw new Error(\"Workbook not found\");\n    }\n\n    const table = wb.get(tableName);\n    if (!table) {\n      throw new Error(\"Table not found\");\n    }\n\n    const newStart = start ? parseCellReference(start) : table.start;\n\n    let newNumRows: SpreadsheetRangeEnd;\n    if (numRows) {\n      newNumRows = numRows;\n    } else {\n      if (table.endRow.type === \"infinity\") {\n        newNumRows = table.endRow;\n      } else {\n        newNumRows = {\n          type: \"number\",\n          value: table.endRow.value - newStart.rowIndex,\n        };\n      }\n    }\n\n    const newTable = this.makeTable({\n      tableName,\n      sheetName: sheetName ?? table.sheetName,\n      workbookName: workbookName ?? table.workbookName,\n      start: getCellReference(newStart),\n      numRows: newNumRows,\n      numCols: numCols ?? table.headers.size,\n      getCellValue,\n    });\n\n    wb.set(tableName, newTable);\n  }\n\n  removeTable({\n    tableName,\n    workbookName,\n  }: {\n    tableName: string;\n    workbookName: string;\n  }): boolean {\n    const wb = this.tables.get(workbookName);\n    if (!wb) {\n      return false;\n    }\n    const found = wb.delete(tableName);\n\n    return found;\n  }\n\n  updateTablesForSheetRename(options: {\n    sheetName: string;\n    newSheetName: string;\n    workbookName: string;\n  }): void {\n    // Update tables that belong to the renamed sheet\n    const wb = this.tables.get(options.workbookName);\n    if (!wb) {\n      // No tables exist for this workbook yet — nothing to update\n      return;\n    }\n\n    wb.forEach((table) => {\n      if (table.sheetName === options.sheetName) {\n        table.sheetName = options.newSheetName;\n      }\n    });\n  }\n\n  updateTablesForWorkbookRename(options: {\n    workbookName: string;\n    newWorkbookName: string;\n  }): void {\n    const wb = this.tables.get(options.workbookName);\n    if (!wb) {\n      // No tables exist for this workbook yet — nothing to update\n      return;\n    }\n    this.tables.set(options.newWorkbookName, wb);\n    this.tables.delete(options.workbookName);\n    // Update tables that belong to the renamed sheet\n    wb.forEach((table, tableName) => {\n      if (table.workbookName === options.workbookName) {\n        table.workbookName = options.newWorkbookName;\n      }\n    });\n  }\n\n  resetTables(newTables: Map<string, Map<string, TableDefinition>>): void {\n    // Clear existing tables without breaking the Map reference\n    this.tables.clear();\n\n    // Repopulate with new tables\n    newTables.forEach((table, workbookName) => {\n      table.forEach((table, tableName) => {\n        let wb = this.tables.get(workbookName);\n        if (!wb) {\n          wb = new Map();\n          this.tables.set(workbookName, wb);\n        }\n        wb.set(tableName, table);\n      });\n    });\n  }\n\n  toSnapshot(): TableManagerSnapshot {\n    return this.tables;\n  }\n\n  restoreFromSnapshot(snapshot: TableManagerSnapshot): void {\n    this.resetTables(snapshot);\n  }\n\n  /**\n   * When adding a workbook, we need to initialize the new maps\n   */\n  addWorkbook(workbookName: string) {\n    this.tables.set(workbookName, new Map());\n  }\n\n  /**\n   * When removing a workbook, we need to remove the maps\n   */\n  removeWorkbook(workbookName: string) {\n    this.tables.delete(workbookName);\n  }\n\n  /**\n   * When removing a sheet, we need to remove the tables that belong to the sheet\n   */\n  removeSheet(opts: { sheetName: string; workbookName: string }): void {\n    // Remove tables that belong to the removed sheet\n    const wb = this.tables.get(opts.workbookName);\n    if (!wb) {\n      throw new Error(\"Workbook not found\");\n    }\n    wb.forEach((table, tableName) => {\n      if (table.sheetName === opts.sheetName) {\n        wb.delete(tableName);\n      }\n    });\n  }\n\n  isCellInTable(cellAddress: CellAddress): TableDefinition | undefined {\n    const { rowIndex, colIndex } = cellAddress;\n\n    // Get all tables for this sheet\n\n    for (const table of this.getTables(cellAddress.workbookName).values()) {\n      // Check each table to see if the cell is within its bounds\n      if (table.sheetName !== cellAddress.sheetName) {\n        continue;\n      }\n\n      const { start, endRow, headers } = table;\n\n      // Check row bounds\n      const isInRowRange =\n        endRow.type === \"infinity\"\n          ? rowIndex >= start.rowIndex\n          : rowIndex >= start.rowIndex && rowIndex <= endRow.value;\n\n      // Check column bounds\n      const endColIndex = start.colIndex + headers.size - 1;\n      const isInColRange =\n        colIndex >= start.colIndex && colIndex <= endColIndex;\n\n      if (isInRowRange && isInColRange) {\n        return table;\n      }\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Check if a range intersects with any table in the given workbook/sheet.\n   * Used to prevent spilling into tables (Excel behavior).\n   */\n  doesRangeIntersectTable(\n    workbookName: string,\n    sheetName: string,\n    range: SpreadsheetRange,\n  ): boolean {\n    for (const table of this.getTables(workbookName).values()) {\n      if (table.sheetName !== sheetName) {\n        continue;\n      }\n\n      // Build the table's range\n      const { start, endRow, headers } = table;\n      const endColIndex = start.colIndex + headers.size - 1;\n\n      const tableRange: SpreadsheetRange = {\n        start: { col: start.colIndex, row: start.rowIndex },\n        end: {\n          col: { type: \"number\", value: endColIndex },\n          row: endRow,\n        },\n      };\n\n      if (checkRangeIntersection(range, tableRange)) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n}\n"
  ],
  "mappings": "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",
  "debugId": "97499A6596939B4B64756E2164756E21",
  "names": []
}