import type Accessor from "../../core/Accessor.js";
import type Entity from "./Entity.js";
import type InputQuantizationParameters from "./InputQuantizationParameters.js";
import type Relationship from "./Relationship.js";

export interface GraphApplyEditsProperties extends Partial<Pick<GraphApplyEdits, "entityAdds" | "entityDeletes" | "entityUpdates" | "options" | "relationshipAdds" | "relationshipDeletes" | "relationshipUpdates">> {}

/**
 * This class defines [entities](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Entity.html) and
 * [relationships](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Relationship.html) to add, delete, and update in a knowledge graph service's
 * [graph](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-KnowledgeGraph.html) resource. Use [entityUpdates](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-GraphApplyEdits.html#entityUpdates)
 * or [relationshipUpdates](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-GraphApplyEdits.html#relationshipUpdates) to change property values.
 *
 * > [!WARNING]
 * >
 * > **Note**
 * >
 * > The user must have [sufficient privileges](https://enterprise.arcgis.com/en/portal/latest/administer/windows/roles.htm#TABLE_1ECAC6C4F7F549AF98045224603F0AD2)
 * > to edit content, and editing must be enabled for the knowledge graph service for this operation to be successful.
 *
 * @since 4.25
 * @see [Sample - Edit knowledge graph data](https://developers.arcgis.com/javascript/latest/sample-code/knowledgegraph-applyedits/)
 * @see [ArcGIS REST APIs - Apply Edits (Graph)](https://developers.arcgis.com/rest/services-reference/enterprise/kgs-graph-applyedits.htm).
 * @see [executeApplyEdits()](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraphService.html#executeApplyEdits)
 * @see [GraphApplyEditsResult](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-GraphApplyEditsResult.html)
 * @example
 * // add a new `Supplier` entity
 * const [knowledgeGraphModule, Entity, GraphApplyEdits] = await $arcgis.import([
 *   "@arcgis/core/rest/knowledgeGraphService.js",
 *   "@arcgis/core/rest/knowledgeGraph/Entity.js",
 *   "@arcgis/core/rest/knowledgeGraph/GraphApplyEdits.js"
 * ]);
 * const newEntity = new Entity({
 *   typeName: "Supplier",
 *   properties: {
 *     Name: "Supplier 5",
 *     EmployeeCount: 681
 *   }
 * });
 *
 * KnowledgeGraphModule.executeApplyEdits(
 *   graph,
 *   new GraphApplyEdits({
 *      entityAdds: [newEntity]
 *    })
 * ).then((editResult) => {
 *    console.log("Graph Add Result", editResult);
 * });
 * @example
 * // add multiple new items
 * const newEntity = new Entity({
 *   typeName: "Supplier",
 *   properties: {
 *     Name: "Supplier 5",
 *     EmployeeCount: 681
 *   },
 * });
 *
 * const newRelationship = new Relationship({
 *   typeName: "buys_part",
 *   properties: {
 *     quantity: 5000
 *   },
 *   // origin and destination entities must already exist in the graph
 *   originId: "{AN4E4G85-41F1-49A4-8412-CACCC9906E88}",
 *   destinationId: "{9D2D6AFD-41F1-49A4-8412-1DGR8E5D6S1G4}"
 * });
 *
 * KnowledgeGraphModule.executeApplyEdits(graph, {
 *    entityAdds: [newEntity],
 *    relationshipAdds: [newRelationship]
 * })
 * .then((editResult) => {
 *   console.log("Graph Add Result", editResult);
 * });
 * @example
 * // update existing records
 * const updateEntity = new Entity({
 *   typeName: "Supplier",
 *   // update the EmployeeCount from 681 to 685
 *   properties: {
 *     Name: "Supplier 5",
 *     EmployeeCount: 685
 *   },
 *   id:"{G1E5G3D4-41F1-49A4-8412-1S5GE8S4D5S1G}" //id of entity already in knowledge graph
 * });
 *
 * const updateRelationship = new Relationship({
 *   typeName: "buys_part",
 *   // update the quantity from 5000 to 5500
 *   properties: {
 *     quantity: 5500
 *   },
 *   id: "{MSIGESNG-A1F5-1A8F-3W5F-15A8W4F3S5F8W}" //id of relationship already in knowledge graph
 * });
 *
 * KnowledgeGraphModule.executeApplyEdits(graph, {
 *    entityUpdates: [updateEntity],
 *    relationshipUpdates: [updateRelationships]
 * })
 * .then((editResult) => {
 *    console.log("Graph Update Result", editResult);
 * });
 * @example
 * // delete existing records
 * KnowledgeGraphModule.executeApplyEdits(graph, {
 *    entityDeletes: [{
 *      typeName: "Supplier",
 *      ids: ["{AMGIE541G-41F1-49A4-8412-CACCC9906E88}", "{HNWIGHE15-WH52-2GE6-1A5W-A1F8W4FS3A1S5}"]
 *    },{
 *      typeName: "Part",
 *      ids: ["{FNIW4GF1-ANFW-49A4-ANW7-GNWIGHAF4S51FS}"]
 *    }],
 *    relationshipDeletes: [{
 *      typeName: "Buys_part",
 *      ids: ["{MH4E54G8E-MF4W-1842-2S44-15AF5W8F4S2W8}"]
 *    }],
 *    // delete all relationships connected to the deleted entities.
 *    options:{
 *      cascadeDelete: true
 *    }
 * })
 * .then((editResult) => {
 *   console.log("Graph Delete Result", editResult);
 * });
 * @example
 * // Basic example results of adding one entity to the `Supplier` entity type
 * {
 *   editResults:[{
 *     adds:[
 *     {
 *       id: "{ANWIFLWF-ANFW-49A4-ANW7-GM51GN5G1878}",
 *       error: false
 *     }],
 *     deletes:[],
 *     typeName: "Supplier",
 *     updates:[]
 *   }],
 *   hasError: false,
 *   error: undefined
 * }
 */
export default class GraphApplyEdits extends Accessor {
  constructor(properties?: GraphApplyEditsProperties);
  /**
   * A list of [entities](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Entity.html) to add to the [knowledge graph](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-KnowledgeGraph.html).
   *
   * @example
   * //add a new `Supplier` entity
   * const newEntity = new Entity({
   *   typeName: "Supplier",
   *   properties: {
   *     Name: "Supplier 5",
   *     EmployeeCount: 681
   *   }
   * });
   *
   * KnowledgeGraphModule.executeApplyEdits(
   *   graph, {
   *     entityAdds: [newEntity],
   * })
   * .then((editResult) => {
   *   console.log("Graph Add Result", editResult);
   * });
   */
  accessor entityAdds: Entity[] | null | undefined;
  /**
   * A list of objects containing an [entity type](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-EntityType.html) and
   * the ids of the [entities](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Entity.html) of that type to delete.
   * Each object must have the`typeName` and `ids` properties.
   *
   * @example
   * entityDeletes: [{
   *    typeName: "Supplier",
   *    ids: ["{AMGIE541G-41F1-49A4-8412-CACCC9906E88}", "{HNWIGHE15-WH52-2GE6-1A5W-A1F8W4FS3A1S5}"]
   *  },{
   *    typeName: "Part",
   *    ids: ["{FNIW4GF1-ANFW-49A4-ANW7-GNWIGHAF4S51FS}"]
   * }]
   */
  accessor entityDeletes: GraphNamedObjectDeletes[] | null | undefined;
  /**
   * A list of [entities](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Entity.html) with the modified properties
   * to update in the [knowledge graph](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-KnowledgeGraph.html).
   */
  accessor entityUpdates: Entity[] | null | undefined;
  /**
   * Additional options to set an [input quantization](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-InputQuantizationParameters.html) for any geometries being added to the graph
   * and to automatically delete all relationships associated with a deleted entity.
   *
   * @default false
   */
  accessor options: GraphApplyEditsOptions | null | undefined;
  /**
   * A list of [relationships](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Relationship.html) to add to the [knowledge graph](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-KnowledgeGraph.html).
   *
   * @example
   * //add a new `Supplier` entity
   * const newRelationship = new Relationship({
   *   typeName: "buys_part",
   *   properties: {
   *     quantity: 18880,
   *   },
   *   originId: "{AN4E4G85-41F1-49A4-8412-CACCC9906E88}",
   *   destinationId: "{9D2D6AFD-41F1-49A4-8412-1DGR8E5D6S1G4}"
   * });
   *
   * KnowledgeGraphModule.executeApplyEdits(
   *   graph, {
   *     relationshipAdds: [newRelationship],
   * })
   * .then((editResult) => {
   *   console.log("Graph Add Result", editResult);
   * });
   */
  accessor relationshipAdds: Relationship[] | null | undefined;
  /**
   * A list of objects containing a [relationship type](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-RelationshipType.html), and
   * the ids of the [relationships](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Relationship.html) of that type to delete.
   * Each object in the array must have the `typeName` and `ids` properties.
   *
   * @example
   * relationshipDeletes: [{
   *   typeName: "Buys_part",
   *   ids: ["{MH4E54G8E-MF4W-1842-2S44-15AF5W8F4S2W8}"]
   * }],
   */
  accessor relationshipDeletes: GraphNamedObjectDeletes[] | null | undefined;
  /**
   * A list of [relationships](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Relationship.html) with modified properties
   * to update in the [knowledge graph](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-KnowledgeGraph.html).
   */
  accessor relationshipUpdates: Relationship[] | null | undefined;
}

export interface GraphApplyEditsOptions {
  /**
   * Custom
   * [quantization parameters](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-InputQuantizationParameters.html)
   * for input geometry that compresses geometry for transfer to the server.
   * Overrides the default lossless WGS84 quantization.
   */
  inputQuantizationParameters?: InputQuantizationParameters;
  /**
   * If `true`, deleting an entity will automatically delete all relationships connected to that entity.
   * If `false`, then both the entity and all it's connected relationships must be provided or the
   * [executeApplyEdits()](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraphService.html#executeApplyEdits) operation will fail.
   */
  cascadeDelete?: boolean;
  /**
   * If `true`, deleting an entity or relationship, or nullifying a property value will automatically delete any linked provenance records.
   * If `false`, then all linked provenance records must be deleted or the
   * [executeApplyEdits()](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraphService.html#executeApplyEdits) operation will fail.
   */
  cascadeProvenanceDelete?: boolean;
}

/**
 * GraphNamedObjectDeletes represents the list of [GraphNamedObjects](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-GraphNamedObject.html) ([entities](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Entity.html)
 * or [relationships](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-Relationship.html)) of a specific type that will be deleted from a knowledge graph.
 *
 * @example
 * //typical use case
 * GraphApplyEdits.entityDeletes = [{
 *    typeName: "Supplier",
 *    ids: ["{AMGIE541G-41F1-49A4-8412-CACCC9906E88}", "{HNWIGHE15-WH52-2GE6-1A5W-A1F8W4FS3A1S5}"]
 *  }]
 */
export interface GraphNamedObjectDeletes {
  /** The name of the [EntityType](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-knowledgeGraph-EntityType.html) that the entities belongs to. */
  typeName: string;
  /** A list of the ids of the specified type to delete. */
  ids: string[];
}