{
  "version": 3,
  "sources": ["../../../../../src/functions/reference/offset/offset.ts"],
  "sourcesContent": [
    "import {\n  FormulaError,\n  type CellValue,\n  type CellNumber,\n  type FunctionDefinition,\n  type FunctionEvaluationResult,\n  type ValueEvaluationResult,\n  type CellAddress,\n  type SpreadsheetRange,\n  type SpilledValuesEvaluationResult,\n  type SingleEvaluationResult,\n  type SpreadsheetRangeEnd,\n} from \"../../../core/types.mjs\";\nimport type { EvaluationContext } from \"../../../evaluator/evaluation-context.mjs\";\nimport type { ReferenceNode, RangeNode } from \"../../../parser/ast.mjs\";\nimport { isCellAddress, isRangeAddress } from \"../../../core/utils.mjs\";\n\n/**\n * OFFSET function - Returns a reference offset from a given reference\n * \n * Usage: OFFSET(reference, rows, cols, [height], [width])\n * \n * reference: The reference from which you want to base the offset\n * rows: The number of rows, up or down, that you want the upper-left cell to refer to\n * cols: The number of columns, left or right, that you want the upper-left cell to refer to\n * height: (optional) The height, in number of rows, that you want the returned reference to be\n * width: (optional) The width, in number of columns, that you want the returned reference to be\n * \n * Examples:\n * - OFFSET(A1, 2, 3) returns the value in cell D3 (2 rows down, 3 columns right from A1)\n * - OFFSET(A1, 0, 0, 3, 1) returns the range A1:A3\n * - OFFSET(A1, 1, 1, 2, 2) returns the range B2:C3\n * \n * Notes:\n * - If rows or cols offset reference from the edge of the worksheet, returns #REF! error\n * - Height and width must be positive\n * - If height or width is omitted, the same height or width as reference is used\n */\nexport const OFFSET: FunctionDefinition = {\n  name: \"OFFSET\",\n  evaluate: function (node, context): FunctionEvaluationResult {\n    if (node.args.length < 3 || node.args.length > 5) {\n      return {\n        type: \"error\",\n        err: FormulaError.VALUE,\n        message: \"OFFSET function requires 3 to 5 arguments\",\n        errAddress: context.dependencyNode,\n      };\n    }\n\n    // Evaluate reference\n    const refResult = this.evaluateNode(node.args[0]!, context);\n    if (\n      refResult.type === \"error\" ||\n      refResult.type === \"awaiting-evaluation\"\n    ) {\n      return refResult;\n    }\n\n    // Evaluate rows offset\n    const rowsResult = this.evaluateNode(node.args[1]!, context);\n    if (\n      rowsResult.type === \"error\" ||\n      rowsResult.type === \"awaiting-evaluation\"\n    ) {\n      return rowsResult;\n    }\n\n    if (rowsResult.type !== \"value\" || rowsResult.result.type !== \"number\") {\n      return {\n        type: \"error\",\n        err: FormulaError.VALUE,\n        message: \"OFFSET function rows must be a number\",\n        errAddress: context.dependencyNode,\n      };\n    }\n\n    // Evaluate cols offset\n    const colsResult = this.evaluateNode(node.args[2]!, context);\n    if (\n      colsResult.type === \"error\" ||\n      colsResult.type === \"awaiting-evaluation\"\n    ) {\n      return colsResult;\n    }\n\n    if (colsResult.type !== \"value\" || colsResult.result.type !== \"number\") {\n      return {\n        type: \"error\",\n        err: FormulaError.VALUE,\n        message: \"OFFSET function cols must be a number\",\n        errAddress: context.dependencyNode,\n      };\n    }\n\n    const rowsOffset = Math.floor(rowsResult.result.value);\n    const colsOffset = Math.floor(colsResult.result.value);\n\n    // Optional height parameter\n    let height: number | undefined;\n    if (node.args.length >= 4) {\n      const heightResult = this.evaluateNode(node.args[3]!, context);\n      if (\n        heightResult.type === \"error\" ||\n        heightResult.type === \"awaiting-evaluation\"\n      ) {\n        return heightResult;\n      }\n\n      if (heightResult.type === \"value\" && heightResult.result.type === \"number\") {\n        height = Math.floor(heightResult.result.value);\n        if (height < 1) {\n          return {\n            type: \"error\",\n            err: FormulaError.VALUE,\n            message: \"OFFSET function height must be positive\",\n            errAddress: context.dependencyNode,\n          };\n        }\n      }\n    }\n\n    // Optional width parameter\n    let width: number | undefined;\n    if (node.args.length === 5) {\n      const widthResult = this.evaluateNode(node.args[4]!, context);\n      if (\n        widthResult.type === \"error\" ||\n        widthResult.type === \"awaiting-evaluation\"\n      ) {\n        return widthResult;\n      }\n\n      if (widthResult.type === \"value\" && widthResult.result.type === \"number\") {\n        width = Math.floor(widthResult.result.value);\n        if (width < 1) {\n          return {\n            type: \"error\",\n            err: FormulaError.VALUE,\n            message: \"OFFSET function width must be positive\",\n            errAddress: context.dependencyNode,\n          };\n        }\n      }\n    }\n\n    // Get the base cell/range from the evaluated reference\n    let baseRange: SpreadsheetRange;\n    let baseSheetName: string = context.cellAddress.sheetName;\n    let baseWorkbookName: string = context.cellAddress.workbookName;\n\n    // Check if we have a cell or range reference\n    const cellOrRange =\n      refResult.type === \"spilled-values\"\n        ? (refResult.sourceCell ?? refResult.sourceRange)\n        : refResult.sourceCell;\n\n    if (!cellOrRange) {\n      return {\n        type: \"error\",\n        err: FormulaError.VALUE,\n        message: \"OFFSET function requires a cell or range reference\",\n        errAddress: context.dependencyNode,\n      };\n    }\n\n    // Extract the base range from sourceCell or sourceRange\n    if (isCellAddress(cellOrRange)) {\n      // It's a CellAddress\n      baseSheetName = cellOrRange.sheetName;\n      baseWorkbookName = cellOrRange.workbookName;\n      baseRange = {\n        start: {\n          col: cellOrRange.colIndex,\n          row: cellOrRange.rowIndex,\n        },\n        end: {\n          col: { type: \"number\", value: cellOrRange.colIndex },\n          row: { type: \"number\", value: cellOrRange.rowIndex },\n        },\n      };\n    } else if (isRangeAddress(cellOrRange)) {\n      // It's a RangeAddress\n      baseSheetName = cellOrRange.sheetName;\n      baseWorkbookName = cellOrRange.workbookName;\n      baseRange = cellOrRange.range;\n    } else {\n      return {\n        type: \"error\",\n        err: FormulaError.VALUE,\n        message: \"OFFSET function requires a cell or range reference\",\n        errAddress: context.dependencyNode,\n      };\n    }\n\n    // Calculate the offset range\n    const offsetStartCol = baseRange.start.col + colsOffset;\n    const offsetStartRow = baseRange.start.row + rowsOffset;\n\n    // Validate bounds (assuming reasonable spreadsheet size)\n    if (offsetStartCol < 0 || offsetStartRow < 0) {\n      return {\n        type: \"error\",\n        err: FormulaError.REF,\n        message: \"OFFSET function resulted in invalid cell reference\",\n        errAddress: context.dependencyNode,\n      };\n    }\n\n    // Calculate end position based on height/width or original range size\n    let offsetEndCol: number;\n    let offsetEndRow: number;\n\n    if (width !== undefined) {\n      offsetEndCol = offsetStartCol + width - 1;\n    } else if (baseRange.end.col.type === \"number\") {\n      offsetEndCol = offsetStartCol + (baseRange.end.col.value - baseRange.start.col);\n    } else {\n      return {\n        type: \"error\",\n        err: FormulaError.VALUE,\n        message: \"OFFSET function requires finite reference when width is omitted\",\n        errAddress: context.dependencyNode,\n      };\n    }\n\n    if (height !== undefined) {\n      offsetEndRow = offsetStartRow + height - 1;\n    } else if (baseRange.end.row.type === \"number\") {\n      offsetEndRow = offsetStartRow + (baseRange.end.row.value - baseRange.start.row);\n    } else {\n      return {\n        type: \"error\",\n        err: FormulaError.VALUE,\n        message: \"OFFSET function requires finite reference when height is omitted\",\n        errAddress: context.dependencyNode,\n      };\n    }\n\n    // Validate the end bounds\n    if (offsetEndCol < 0 || offsetEndRow < 0) {\n      return {\n        type: \"error\",\n        err: FormulaError.REF,\n        message: \"OFFSET function resulted in invalid cell reference\",\n        errAddress: context.dependencyNode,\n      };\n    }\n\n    // Create the offset range\n    const offsetRange: SpreadsheetRange = {\n      start: {\n        col: offsetStartCol,\n        row: offsetStartRow,\n      },\n      end: {\n        col: { type: \"number\", value: offsetEndCol },\n        row: { type: \"number\", value: offsetEndRow },\n      },\n    };\n\n    // If it's a single cell, return its value\n    if (offsetStartCol === offsetEndCol && offsetStartRow === offsetEndRow) {\n      return this.evaluateReference(\n        {\n          type: \"reference\",\n          address: {\n            colIndex: offsetStartCol,\n            rowIndex: offsetStartRow,\n          },\n          sheetName: baseSheetName,\n          workbookName: baseWorkbookName,\n          isAbsolute: {\n            col: true,\n            row: true,\n          },\n        },\n        context\n      );\n    }\n\n    // Otherwise, return a range reference (spilled values)\n    return this.evaluateRange(\n      {\n        type: \"range\",\n        range: offsetRange,\n        sheetName: baseSheetName,\n        workbookName: baseWorkbookName,\n        isAbsolute: {\n          start: { col: true, row: true },\n          end: { col: true, row: true },\n        },\n      },\n      context\n    );\n  },\n};\n"
  ],
  "mappings": "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",
  "debugId": "BFCF32D44167F3BD64756E2164756E21",
  "names": []
}