import type Accessor from "@arcgis/core/core/Accessor.js";
import type Graphic from "@arcgis/core/Graphic.js";
import type Layer from "@arcgis/core/layers/Layer.js";
import type SubtypeGroupLayer from "@arcgis/core/layers/SubtypeGroupLayer.js";
import type FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
import type GraphicsLayer from "@arcgis/core/layers/GraphicsLayer.js";
import type Collection from "@arcgis/core/core/Collection.js";
import type SceneView from "@arcgis/core/views/SceneView.js";
import type MapView from "@arcgis/core/views/MapView.js";
import type SubtypeSublayer from "@arcgis/core/layers/support/SubtypeSublayer.js";
import type BatchAttributeFormViewModel from "@arcgis/core/widgets/BatchAttributeForm/BatchAttributeFormViewModel.js";
import type TemplateListItem from "@arcgis/core/editing/templates/TemplateListItem.js";
import type { EsriClipboard, ClipboardItem as EsriClipboardItem } from "@arcgis/core/applications/Components/clipboard.js";
import type { ApplySet, ApplySetLayerEditResult, ApplySetServiceEditResult } from "@arcgis/core/applications/Components/applySetUtils.js";
import type { ClipboardMove } from "./ClipboardMove.js";
import type { ResourceHandle } from "@arcgis/core/core/Handles.js";
import type { PasteCommand, PasteApplyError, PasteCommandApplyParameters } from "./commands/PasteCommand.js";
import type { CustomPasteCommand } from "./commands/PasteCustomCommand.js";

/** @internal */
export interface PasteViewModelProperties extends Partial<Pick<PasteViewModel, "_activeFlowPage" | "activeCommand" | "activeFlowPage" | "alwaysShowFeatureForm" | "applying" | "bauActiveFeatureIndex" | "bauApplySet" | "bauFeatures" | "bauFormUpdating" | "bauFormValid" | "bauHasTooManyComplexFeatures" | "bauHasTooManyFeatures" | "bauHighlight" | "bauIndividualHighlight" | "bauInvalidFeatures" | "bauOriginalGraphics" | "beforeClipboard" | "beforeForm" | "clipboardGraphicsLayer" | "clipboardMover" | "closeOnApply" | "currentPasteOperation" | "customPasteCommands" | "formViewModelMap" | "hideErrorNotice" | "hideFooter" | "hideFooterCancelButton" | "hideHeaderCloseButton" | "hideTooltips" | "hideViewClipboard" | "highlightGroup" | "lastPasteError" | "layerPermissionsCheck" | "maximumFeatureCount" | "maximumFeatureCountWithComplexForms" | "pasteTemplate" | "pasteWithAttributes" | "pasteWithMultipleFeaturesEnabled" | "pasteWithMultipleLayersEnabled" | "selectedClipboardItemIndex" | "selectedFeature" | "showClipboardItems" | "supportedCommands" | "view">> {}

/**
 * The types of flow page that maybe being shown in the component
 *
 * @internal
 */
export type ActiveFlowPage = "clipboard-empty-page" | "clipboard" | "commands-page" | "form-page" | "gallery-page" | "merge-page" | "no-command-page";

/**
 * The types of supported paste operation
 * These maybe explicit ones, supported by the component, or user defined (as in string)
 *
 * @internal
 */
export type SupportedPasteCommand = "paste-append" | "paste-as" | "paste-merge" | "paste-subtract" | "paste" | (string & {});

/** @internal */
export default class PasteViewModel extends Accessor {
  constructor(properties?: PasteViewModelProperties);
  /** @default "commands-page" */
  accessor _activeFlowPage: ActiveFlowPage;
  accessor activeCommand: SupportedPasteCommand | undefined;
  accessor activeFlowPage: ActiveFlowPage;
  get allCommands(): PasteCommand[];
  /** @default false */
  accessor alwaysShowFeatureForm: boolean;
  /** @default false */
  accessor applying: boolean;
  get availableCommands(): PasteCommand[];
  /** @default -1 */
  accessor bauActiveFeatureIndex: number;
  get bauActiveGraphic(): Graphic | undefined;
  get bauActiveLayer(): FeatureLayer | SubtypeGroupLayer | undefined;
  accessor bauApplySet: ApplySet | undefined;
  accessor bauFeatures: Collection<Graphic> | undefined;
  /** @default false */
  accessor bauFormUpdating: boolean;
  /** @default true */
  accessor bauFormValid: boolean;
  /** @default false */
  accessor bauHasTooManyComplexFeatures: boolean;
  /** @default false */
  accessor bauHasTooManyFeatures: boolean;
  accessor bauHighlight: ResourceHandle | undefined;
  accessor bauIndividualHighlight: {
      graphic: Graphic;
      handle: ResourceHandle;
  } | undefined;
  accessor bauInvalidFeatures: Graphic[];
  accessor bauOriginalGraphics: {
      graphic: Graphic;
      layer: FeatureLayer | SubtypeGroupLayer;
  }[];
  accessor beforeClipboard: ActiveFlowPage | undefined;
  accessor beforeForm: ActiveFlowPage | undefined;
  get canCreateOnAllLayers(): boolean;
  get clipboard(): EsriClipboard;
  get clipboardAndTemplateSupportAttributes(): boolean;
  get clipboardFeatures(): Collection<EsriClipboardItem>;
  accessor clipboardGraphicsLayer: GraphicsLayer | undefined;
  get clipboardItemLayers(): Layer[];
  accessor clipboardMover: ClipboardMove | undefined;
  /** @default false */
  accessor closeOnApply: boolean;
  /** @default "" */
  accessor currentPasteOperation: "" | "paste-as" | "paste-merge";
  accessor customPasteCommands: Collection<CustomPasteCommand>;
  accessor formViewModelMap: Map<FeatureLayer | SubtypeSublayer, BatchAttributeFormViewModel>;
  get hasClipboardItemMatchingTemplate(): boolean;
  get hasPasteCommandsPage(): boolean;
  get hasTooManyPasteCreateFeatures(): boolean;
  /** @default false */
  accessor hideErrorNotice: boolean;
  /** @default false */
  accessor hideFooter: boolean;
  /** @default false */
  accessor hideFooterCancelButton: boolean;
  /** @default false */
  accessor hideHeaderCloseButton: boolean;
  /** @default false */
  accessor hideTooltips: boolean;
  /** @default false */
  accessor hideViewClipboard: boolean;
  /** @default "temporary" */
  accessor highlightGroup: string;
  accessor lastPasteError: PasteApplyError | undefined;
  accessor layerPermissionsCheck: {
      canUpdate: (layer: FeatureLayer | null | undefined | SubtypeGroupLayer) => boolean;
      canCreate: (layer: FeatureLayer | null | undefined | SubtypeGroupLayer) => boolean;
  };
  /**
   * The maximum number of features that can be loaded into the form.
   *
   * @default 200
   */
  accessor maximumFeatureCount: number;
  /**
   * The number of features that can be loaded into the form.
   * This is used to determine whether the form can be loaded with forms containing complex Arcade expressions.
   *
   * @default 50
   */
  accessor maximumFeatureCountWithComplexForms: number;
  get pasteCommandsState(): {
      id: SupportedPasteCommand;
      disabled: boolean;
      available: boolean;
  }[];
  accessor pasteTemplate: TemplateListItem | undefined;
  get pasteTemplateIsValid(): boolean;
  /** @default true */
  accessor pasteWithAttributes: boolean;
  /** @default false */
  accessor pasteWithMultipleFeaturesEnabled: boolean;
  /** @default false */
  accessor pasteWithMultipleLayersEnabled: boolean;
  /** @default -1 */
  accessor selectedClipboardItemIndex: number;
  accessor selectedFeature: Graphic | undefined;
  /** @default false */
  accessor showClipboardItems: boolean;
  accessor supportedCommands: SupportedPasteCommand[];
  get updating(): boolean;
  accessor view: MapView | SceneView | undefined;
  get workingLayers(): (FeatureLayer | SubtypeGroupLayer)[];
  checkAndSuspendMove(): void;
  clearHighlightSelectedGraphic(): void;
  clearIndividualFeatureFormHighlight(): void;
  clearMultiFeatureFormHighlights(): void;
  /**
   * @param originalGraphic
   * @param newFieldValues
   */
  formFeatureValuesChanged(originalGraphic: {
      graphic: Graphic;
      layer: FeatureLayer | SubtypeGroupLayer;
  }, newFieldValues: Record<string, unknown> | undefined): void;
  /** @param id */
  getPasteCommandById(id?: SupportedPasteCommand): PasteCommand | undefined;
  /**
   * @param outcome
   * @param onPasteError
   */
  handleApplyError(outcome: {
      success: boolean;
      errorCode?: string;
      errorMessage?: string;
  }, onPasteError: (error: PasteApplyError) => void): void;
  /**
   * @param graphic
   * @param _graphicIndex
   */
  highlightMultiFeatureFormFeature(graphic: Graphic, _graphicIndex: number): void;
  /** @param listItem */
  highlightSelectedGraphicOnMap(listItem: EsriClipboardItem): void;
  nextActiveFeature(): void;
  previousActiveFeature(): void;
  resetFormPage(): void;
  resetHome(): void;
  /** @param params */
  runPasteFormCommand(params: PasteCommandApplyParameters): Promise<void>;
  updateClipboardGraphicsLayer(): void;
  updateIndividualMultiFeatureFormHighlight(): void;
  /** @param applySet */
  writeChanges(applySet: ApplySet): Promise<(ApplySetLayerEditResult | ApplySetServiceEditResult)[]>;
}