import type Field from "@arcgis/core/layers/support/Field.js";
import type KnowledgeGraph from "@arcgis/core/rest/knowledgeGraph/KnowledgeGraph.js";
import type { GeometryUnion } from "@arcgis/core/geometry/types.js";

/** @internal */
export interface IArcadeRuntimeDictionary {
  declaredClass?: string;
  arcadeDeclaredClass?: string;
  keys: () => string[];
  field: (name: string) => unknown;
  geometry?: () => GeometryUnion;
  castAsJson: () => Record<string, unknown>;
}

/** @internal */
export interface IAbortSignal {
  aborted: boolean;
}

/** @internal */
export interface IArcadeRuntimeFeatureSet {
  declaredRootClass: string;
  fields: Field[] | null;
  load: () => Promise<IArcadeRuntimeFeatureSet>;
  iterator: (abortSignal: IAbortSignal) => IArcadeRuntimeFeatureSetIterator;
}

/** @internal */
export interface IArcadeRuntimeFeatureSetIterator {
  nextBatchAsArcadeFeatures: (bsize: number, timeZone: string) => Promise<IArcadeRuntimeDictionary[] | null>;
}

/** @internal */
export interface IArcadeRuntimeImmutableArray {
  length: () => number;
  get: (index: number) => unknown;
  toArray: () => unknown[];
  _elements: unknown[];
}

/** @internal */
export interface IArcadeRuntimeDate {
  declaredRootClass: string;
  toDateTime: () => { setLocale: (locale: string) => { toFormat: (format: string) => string; }; };
  isUnknownTimeZone: boolean;
}

/** @internal */
export interface IArcadeRuntimeDateOnly {
  declaredRootClass: string;
  /** To ISO Date format */
  toString: () => string;
}

/** @internal */
export interface IArcadeRuntimeTimeOnly {
  declaredRootClass: string;
  /** To ISO Time format */
  toString: () => string;
}

/** @internal */
export type ResultType = "array" | "attachment" | "boolean" | "date" | "dateOnly" | "dictionary" | "error" | "feature" | "featureSet" | "geometry" | "knowledgeGraph" | "null" | "number" | "pixel" | "portal" | "text" | "time" | "unknown";

/** @internal */
export interface IArcadeResultBase {
  type: ResultType;
  timeStamp?: Date;
  compilationTime?: number;
  executionTime?: number;
}

/** @internal */
export interface IArcadeResultUnknown extends IArcadeResultBase {
  type: "unknown";
}

/** @internal */
export interface IArcadeResultNull extends IArcadeResultBase {
  type: "null";
}

/** @internal */
export interface IArcadeResultError extends IArcadeResultBase {
  type: "error";
  value: string;
  error: unknown;
}

/** @internal */
export interface IArcadeResultArray extends IArcadeResultBase {
  type: "array";
  value: unknown[];
}

/** @internal */
export interface IArcadeResultDate extends IArcadeResultBase {
  type: "date";
  value: Date | IArcadeRuntimeDate;
}

/** @internal */
export interface IArcadeResultDateOnly extends IArcadeResultBase {
  type: "dateOnly";
  value: IArcadeRuntimeDateOnly;
}

/** @internal */
export interface IArcadeResultTimeOnly extends IArcadeResultBase {
  type: "time";
  value: IArcadeRuntimeTimeOnly;
}

/** @internal */
export interface IArcadeResultString extends IArcadeResultBase {
  type: "text";
  value: string;
}

/** @internal */
export interface IArcadeResultNumber extends IArcadeResultBase {
  type: "number";
  value: number;
}

/** @internal */
export interface IArcadeResultBoolean extends IArcadeResultBase {
  type: "boolean";
  value: boolean;
}

/** @internal */
export interface IArcadeResultDictionary extends IArcadeResultBase {
  type: "dictionary";
  value: IArcadeRuntimeDictionary;
}

/** @internal */
export interface IArcadeResultGeometry extends IArcadeResultBase {
  type: "geometry";
  value: GeometryUnion;
}

/** @internal */
export interface IArcadeResultKnowledgeGraph extends IArcadeResultBase {
  type: "knowledgeGraph";
  value: KnowledgeGraph;
}

/** @internal */
export interface IArcadeResultFeature extends IArcadeResultBase {
  type: "feature";
  value: IArcadeRuntimeDictionary;
}

/** @internal */
export interface IArcadeResultPixel extends IArcadeResultBase {
  type: "pixel";
  value: IArcadeRuntimeDictionary;
}

/** @internal */
export interface IArcadeResultFeatureSet extends IArcadeResultBase {
  type: "featureSet";
  value: IArcadeRuntimeFeatureSet;
  iterator: IArcadeRuntimeFeatureSetIterator | null;
  features: IArcadeRuntimeDictionary[];
}

/** @internal */
export interface IArcadeResultPortal extends IArcadeResultBase {
  type: "portal";
  value: IArcadeRuntimeDictionary;
}

/** @internal */
export interface IArcadeResultAttachment extends IArcadeResultBase {
  type: "attachment";
  value: IArcadeRuntimeDictionary;
}

/** @internal */
export type ArcadeResult = IArcadeResultArray | IArcadeResultAttachment | IArcadeResultBoolean | IArcadeResultDate | IArcadeResultDateOnly | IArcadeResultDictionary | IArcadeResultError | IArcadeResultFeature | IArcadeResultFeatureSet | IArcadeResultGeometry | IArcadeResultKnowledgeGraph | IArcadeResultNull | IArcadeResultNumber | IArcadeResultPixel | IArcadeResultPortal | IArcadeResultString | IArcadeResultTimeOnly | IArcadeResultUnknown;