/// <reference types="@arcgis/core/interfaces.d.ts" />
import type { UserSession } from "@esri/solution-common";
import type { MapPicker } from "../components/map-picker/customElement.js";
import type { MapLayerPicker } from "../components/map-layer-picker/customElement.js";
import type { IPagedResponse } from "@esri/arcgis-rest-types";
import type { SolutionDeployedCard } from "../components/solution-deployed-card/customElement.js";
import type { Controller } from "@arcgis/lumina/controllers";
import type { Auth } from "./Auth.js";
import type { Telemetry } from "@esri/telemetry";
import type { Icon as Icon } from "@esri/calcite-components/components/calcite-icon";

export type ELayoutMode = "GRID" | "HORIZONTAL" | "VERTICAL";

export type EPageType = "LIST" | "SELECT" | "EXPORT" | "REFINE";

export type ESegmentType = "STANDARD" | "CUSTOM";

export type ESelectionMode = "ADD" | "REMOVE";

export type ESelectionType = "POINT" | "LINE" | "POLY" | "RECT";

export type EWorkflowType = "SEARCH" | "SELECT" | "SKETCH" | "REFINE";

export type EExportType = "CSV" | "PDF";

export type EDrawMode = "SKETCH" | "REFINE";

export const BATCH_EDIT_LIMIT: 500;

export type DistanceUnit = "feet" | "meters" | "miles" | "kilometers";

export type theme = "light" | "dark";

export type ScopeType = "all-solutions" | "deployments";

export type TooltipPlacement = "auto" | "top" | "right" | "bottom" | "left" | "top-start" | "top-end" | "right-start" | "right-end" | "bottom-start" | "bottom-end" | "left-start" | "left-end" | "auto-start" | "auto-end" | "leading-start" | "leading" | "leading-end" | "trailing-end" | "trailing" | "trailing-start";

export interface IMapClick {
  mapPoint: __esri.Point;
  screenPoint: __esri.MapViewScreenPoint;
  x: number;
  y: number;
  button: number;
  buttons: 0 | 1 | 2;
  type: string;
  stopPropagation: any;
  timestamp: number;
  native: PointerEvent;
}

export interface IDeleteIds {
  ids: number[];
}

export interface IRefineOperation {
  ids: number[];
  mode: ESelectionMode;
  layerView: __esri.FeatureLayerView;
}

export interface ISearchConfiguration {
  activeSourceIndex?: number;
  allPlaceholder?: string;
  includeDefaultSources?: boolean;
  searchAllEnabled?: boolean;
  sources?: Array<ILocatorSourceConfigItem | ILayerSourceConfigItem>;
}

export interface ISearchSourceConfigItem {
  maxResults: number;
  maxSuggestions: number;
  minSuggestCharacters: number;
  name: string;
  suggestionsEnabled: boolean;
  placeholder: string;
  withinViewEnabled: boolean;
  zoomScale: number;
  outFields?: string[];
}

export interface ILocatorSourceConfigItem extends ISearchSourceConfigItem {
  url?: string;
  singleLineFieldName: string;
  countryCode: string;
}

export interface ILayerSourceConfigItem extends ISearchSourceConfigItem {
  displayField: string;
  exactMatch: boolean;
  layer: {
      url: string | __esri.FeatureLayer;
      id: string;
  };
  outFields: string[];
  searchFields: string;
  popupTemplate: any;
  popupEnabled: boolean;
}

export interface IDropdownItem {
  displayValue: string;
  sortType: SortType;
}

export interface ISearchSortSettings extends ISearchOption, ISortOption {
  isOrgSolutions: boolean;
}

export interface IScopeSearchSortSettings {
  scope: ScopeType;
  settings: ISearchSortSettings;
}

export interface ISearchTerm {
  searchTerm: string;
  scope: ScopeType;
}

export interface ISortType {
  sortType: SortType;
  scope: ScopeType;
}

export interface IValueChange {
  oldValue: number | string;
  newValue: number | string;
}

/** Layer or table id and title key value pair */
export type IMapItemHash = { [key: string]: ILayerHashInfo; };

export interface ILayerHashInfo {
  name: string;
  supportsUpdate: boolean;
}

/** Stores the id, type, and title for a given template */
export interface ITemplateInfo {
  id: string;
  title: string;
  type: string;
  typeKeywords: string[];
  snippet: string;
  url?: string;
}

export type ILayerItemsHash = { [key: string]: ILayerDetailsHash; };

export interface ILayerDetailsHash {
  name: string;
  formattedFeatureCount: string;
  supportsUpdate: boolean;
  supportsAdd: boolean;
}

/** A templates share details */
export interface ISearchConfig {
  layers: string[];
  layerUrl: string;
  locators: string[];
  locatorUrl: string;
}

export interface ISearchResult {
  graphics: __esri.Graphic[];
  name: string;
}

export interface ISelectionSet {
  id: number;
  searchResult: any;
  buffer?: __esri.Geometry;
  distance: number;
  download: boolean;
  unit: DistanceUnit;
  label: string;
  selectedIds: number[];
  layerView?: __esri.FeatureLayerView;
  geometries: __esri.Geometry[];
  graphics: __esri.Graphic[];
  selectLayers: __esri.FeatureLayerView[];
  skipGeomOIDs?: number[];
  workflowType: EWorkflowType;
  searchDistanceEnabled: boolean;
  useLayerFeaturesEnabled: boolean;
  refineInfos: IRefineInfo;
  redoStack?: IRefineOperation[];
  undoStack?: IRefineOperation[];
  sketchGraphic?: __esri.Graphic;
  undoGraphicsArr?: any[];
}

export type IRefineInfo = { [key: string]: IRefineIds; };

export interface IRefineIds {
  addIds: number[];
  removeIds: number[];
  layerView: __esri.FeatureLayerView;
}

export interface ISketchGraphicsChange {
  graphics: __esri.Graphic[];
  useOIDs: boolean;
}

export interface IQueryExtentResponse {
  count: number;
  extent: __esri.Extent | null;
}

export interface IBeforeLayerSelectionChange {
  currentId?: string;
  currentIds?: string[];
  newId?: string;
  newIds?: string[];
  ref: MapLayerPicker;
}

export interface IBeforeMapChange {
  currentId: string;
  mapInfo: IMapInfo;
  ref: MapPicker;
}

export interface IMapInfo {
  id: string;
  name: string;
  searchConfiguration?: ISearchConfiguration;
  filterConfig?: IFilterConfig;
  _hasValidLayers?: boolean;
  visible?: boolean;
  layerOptions?: ILayerOptions;
  enableInlineEdit: boolean;
  enableCreateFeatures: boolean;
  createFeatureButtonLabel: string;
  enableEditGeometry: boolean;
  enableTableAutosave: boolean;
}

export interface ILayerOptions {
  layers: ILayerDef[];
  mapId?: string;
  configLayerOrder?: string[];
}

export interface ILayerDef {
  id: string;
  sublayerId?: number;
  fields?: string[];
  extraFields: string[];
  fieldOrder?: string[];
  sortField?: string;
  sortOrder?: "asc" | "desc";
}

export interface IMapChange {
  id: string;
  mapView?: __esri.MapView;
  isValid: boolean;
}

export type IExportInfos = { [key: string]: IExportInfo; };

export interface IExportInfo {
  ids: number[];
  layer?: __esri.FeatureLayer;
  layerView?: __esri.FeatureLayerView;
  selectionSetNames: string[];
}

export interface IBasemapConfig {
  basemapIdsToFilter: string[];
  basemapGroupId: string;
}

export interface IToolInfo {
  active: boolean;
  icon: Icon["icon"];
  indicator: boolean;
  func: any;
  label: string;
  toolTip: string;
  disabled: boolean;
  isDanger?: boolean;
  loading?: boolean;
}

export type IColumnsInfo = { [key: string]: boolean; };

export interface IFilterConfig {
  mapId: string;
  layerExpressions: ILayerExpression[];
}

export interface ILayerExpression {
  id: string;
  sublayerId: number;
  title: string;
  expressions: IExpression[];
  operator: string;
}

export interface IImageExtraction {
  field: string;
  id: string;
  prompt: string;
}

export type ExpressionField = "string" | "number" | "date" | "coded-value" | "range" | "checkbox";

export type EditType = "update" | "add" | "delete";

export type ButtonType = "button" | "action";

export type AppLayout = "mapView" | "tableView" | "splitView";

export type VisibilityIconType = "checkbox" | "eyeball";

export interface IExpression {
  id: number;
  type?: ExpressionField;
  active?: boolean;
  definitionExpression?: string;
  name: string;
  field?: string;
  fields?: string[] | number[];
  selectedFields?: string[] | number[];
  codedValues?: { [key: string]: string; };
  placeholder?: string;
  min?: number | string;
  max?: number | string;
  range?: {
      min: string | number | undefined;
      max: string | number | undefined;
  };
  step?: number;
  numDisplayOption?: "slider" | "drop-down";
}

export interface ILayerAndTableIds {
  layerIds: string[];
  tableIds: string[];
}

export interface IPopupUtils {
  /**
   * @param graphic
   * @param map
   */
  getPopupTitle(graphic: __esri.Graphic, map: __esri.Map): Promise<string>;
}

export interface IConsentResponse {
  granted: boolean;
}

export interface IPNContext extends Controller {
  managedLayers: IManagedLayers;
  managedTables: string[];
  highlightHandles: any[];
  removeHandles: () => void;
}

/** Key is the layer name and the value is the type of layer */
export type IManagedLayers = { [key: string]: "buffer" | "sketch"; };

/** Key is the layers guid */
export type IReportingOptions = { [key: string]: IReportingOption; };

export interface IReportingOption {
  reporting: boolean;
  comment: boolean;
  like: boolean;
  likeField?: string;
  dislike: boolean;
  dislikeField?: string;
  visible: boolean;
}

export interface ISortingInfo {
  field: string;
  order: "asc" | "desc";
}

export interface ISolutionItemHover {
  itemId: string;
  entering: boolean;
}

export interface ISolutionItemSelected {
  itemId: string;
  selected: boolean;
}

export interface ISolutionTypeHover {
  itemType: string;
  entering: boolean;
}

export type ChipType = "new" | "deployed" | "updated";

export type SortType = "relevance" | "title" | "new" | "updated" | "suggested" | "created";

export type SortOrder = "asc" | "desc";

export type FilterType = "type" | "industry" | "domain" | "owner";

export const EIndustry: {
    AEC: string;
    AIRPORTPORTRAIL: string;
    BUSINESS: string;
    CONSERVATION: string;
    DEFENSE: string;
    FACILITIES: string;
    HEALTHANDHUMANSERVICES: string;
    PIPELINE: string;
    PUBLICSAFETY: string;
    RENEWABLES: string;
    STATEANDLOCALGOVERNMENT: string;
    TELECOMMUNICATIONS: string;
    UTILITIES: string;
};

export const EDomain: {
    AIRPORT: string;
    AGRICULTURE: string;
    ASSESSMENTANDTAXATION: string;
    DISTRICTENERGY: string;
    ELECTIONS: string;
    ELECTRIC: string;
    EMERGENCYMANAGEMENT: string;
    ENVIRONMENTANDNATURALRESOURCES: string;
    FIRESERVICE: string;
    FISHANDWILDLIFE: string;
    GAS: string;
    HEALTHANDHUMANSERVICES: string;
    LAWENFORCEMENT: string;
    NATURALRESOURCES: string;
    PARKS: string;
    PLANNINGANDDEVELOPMENT: string;
    PROTECTEDAREAS: string;
    PUBLICWORKS: string;
    SEWER: string;
    STORMWATER: string;
    TELECOMMUNICATIONS: string;
    TRANSPORTATION: string;
    WATER: string;
};

export type EType = "New Release" | "Suggested";

export type EOwnerOption = "My solutions" | `My organization's solutions`;

export interface IFilterOption {
  type: FilterType;
  displayValue: string;
  domain?: string;
  value: string | EType | EOwnerOption;
  industry?: string;
}

export interface IFilterSetting {
  categories?: IFilterOption[];
  searchTerm?: string;
}

export interface ISearchOption {
  searchTerm: string;
}

export interface ISortOption {
  sortType: SortType;
  enabled?: boolean;
}

export interface ISolutionDeployedCard {
  deployedDate: string;
  description: string;
  heading: string;
  itemId: string;
  owner: string;
  thumbnail: string;
  updateAvailable: boolean;
}

export interface IDeployedSolutionCards {
  cards: ISolutionInfoCard[];
  relatedSolutions: Set<string>;
}

export const BASE_DEPLOYED_TERMS: "((typekeywords:Solution,Deployed,\"ArcGIS Solution\") OR ((typekeywords:Solution,Deployed) AND (created:[1577862000000 TO 1622576880000])))";

export const BASE_SOLUTIONS_TERMS: "(typekeywords:Solution,Template)";

export interface ISearchOptionPartial {
  q: string;
  filter: string;
  sortField: string;
  sortOrder: string;
  nextStart?: any;
  categories: string[];
  delay: boolean;
  getSuggested?: boolean;
}

export interface ICacheBatch<T> {
  cards: T[];
  paging: IPagedResponse;
}

export type IKeyedStrings = { [key: string]: string; };

export interface IPreview {
  name: string;
  format: string;
  alt: string;
}

/** Summary of a solution item. */
export interface ISolutionInfoCard extends ISortableItem {
  id: string;
  title: string;
  snippet: string;
  description: string;
  url: string;
  itemUrl: string;
  thumbnailFilename: string;
  thumbnailUrl: string;
  tryitUrl: string;
  typeKeywords: string[];
  learnMoreUrl: string;
  createdMs: number;
  created: string;
  modified: string;
  numViews: number;
  tags: string[];
  categories: string[];
  licenseInfo: string;
  deployCommonId: string;
  deployVersion: string;
  canDelete: boolean;
  preview?: IPreview[];
  sourcePortalUrl: string;
  knownToBePublicSource: boolean;
  waitId: string;
  relatedSolutions: string[];
  owner?: string;
  chips?: ChipType[];
  supportReuse?: boolean;
}

export type TEnvironments = "dev" | "qa" | "prod";

export interface ICacheBatch<T> {
  cards: T[];
  paging: IPagedResponse;
}

export type ISortableItem = { [key: string]: any; } & {
  createdMs: number;
  numViews: number;
  title: string;
};

export interface ISpatialReference {
  label: string;
  wkid: number;
  defaultExtent: string;
}

export interface IURLParamPair {
  k: string;
  v: string;
}

export interface IRequestDeploySolution {
  card: ISolutionInfoCard;
  reuse: boolean;
  jobId: string;
  userOptions: IUserOption[];
}

export interface IUserOption {
  id: string;
  props: IUserProp[];
  accordionDisplay?: boolean;
}

export interface IUserProp {
  autoSelect?: boolean;
  id?: string;
  itemType?: string;
  label?: string;
  prop?: string;
  default?: string;
  value?: string;
  responseValue?: string;
  choices?: string[];
  valueType?: string;
  attributes?: any;
  validation?: any;
  valid?: boolean;
  validId?: boolean;
  srSearchText?: string;
  outType?: string;
  loading?: boolean;
  tooltip?: string;
  name?: string;
  title?: string;
  itemUrl?: string;
  existingItemId?: string;
}

export interface IValidNameStatus {
  status: boolean;
  type: "" | "empty" | "exceed length" | "not unique" | "special character";
}

export type TrackingEnv = "dev" | "qa" | "prod" | "";

export interface IDeployProgressUpdate {
  id: string;
  progress: number;
}

export interface IDeployFailed {
  card: ISolutionInfoCard;
  jobId: string;
  error?: any;
}

export const PORTAL_ADD_MEMBERS_TO_GROUP: "portal:user:addExternalMembersToGroup";

export const PORTAL_CREATE_ITEM: "portal:user:createItem";

export const PORTAL_CREATE_GROUP: "portal:user:createGroup";

export const PORTAL_PUBLISH_BD_ANALYTICS: "portal:publisher:publishBigDataAnalytics";

export const PORTAL_PUBLISH_FEATURES: "portal:publisher:publishFeatures";

export const PORTAL_PUBLISH_FEEDS: "portal:publisher:publishFeeds";

export const PORTAL_PUBLISH_GP: "portal:publisher:publishServerGPServices";

export const PORTAL_PUBLISH_RT_ANALYTICS: "portal:publisher:publishRealTimeAnalytics";

export const PORTAL_SHARE_TO_GROUP: "portal:user:shareToGroup";

export const SOLUTIONS_HUB_PREMIUM: "solutions:hubPremium";

export const SOLUTIONS_NOTEBOOK: "solutions:notebook";

export const SOLUTIONS_TRACKING_ADMIN_TRACKING: "solutions:locationtracking:admin:tracking";

export const SOLUTIONS_TRACKING: "solutions:locationtracking:tracking";

export const SOLUTIONS_TRACKING_ADMIN: "solutions:locationtracking:admin";

export const SOLUTIONS_VELOCITY: "solutions:velocity";

export const SOLUTIONS_WORKFLOW_MANAGER: "solutions:workflowManager";

export interface IItemPreview {
  name: string;
  format: string;
  alt: string;
}

export interface IInfoProduct {
  item: string;
  description: string;
  userType: string;
}

export interface IReleaseNote {
  version: string;
  description: string;
}

export interface IItemProperties {
  schemaVersion: number;
  learnMoreUrl: string;
  preview: IItemPreview[];
  relatedSolutions: string[];
  requirements: string[];
  infoProducts: IInfoProduct[];
  releaseNotes: IReleaseNote[];
  dataDictionaryURL: string;
  demoURL: string;
  relatedResources: any[];
}

export interface IPrivilegeMessages {
  leadingMessages: string[];
  bulletedMessages: string[];
  trailingMessages: string[];
}

export type IDeployedSolutionCardRefs = { [key: string]: SolutionDeployedCard; };

export const ITEM_TITLE_LENGTH: 250;

export type DeployAppTab = "all-solutions" | "deployments" | "details" | "resources" | "deployed-card" | "my-content";

export interface IActiveTab {
  tabType: DeployAppTab;
  tabTitleOrId: string;
}

export type FieldSortType = "default" | "display" | "field" | "type";

export type NameType = "folder" | "item";

export const TELEMETRY_CATEGORY: {
    readonly SOLUTION_DETAILS: "Solution Details";
    readonly GLOBAL_NAVIGATION: "Global Nav";
    readonly ALL_SOLUTIONS: "Solutions";
    readonly DEPLOYMENTS: "Deployments";
    readonly ASSISTANT: "Assistant";
    readonly RESOURCES: "Resources";
};

export type TelemetryCategory = typeof TELEMETRY_CATEGORY[keyof typeof TELEMETRY_CATEGORY];

export interface ITelemetryDimensions {
  dimension1?: string;
  dimension2?: string;
  dimension3?: string;
  dimension4?: string;
  dimension5?: string;
  dimension6?: string;
  dimension7?: string;
  dimension8?: string;
  dimension9?: string;
  dimension10?: string;
  dimension11?: string;
  dimension12?: string;
  dimension13?: string;
  dimension14?: string;
  dimension15?: string;
  dimension16?: string;
  dimension17?: string;
  dimension18?: string;
  dimension19?: string;
  dimension20?: string;
}

export interface ITelemetryMetrics {
  metric1?: number;
  metric2?: number;
  metric3?: number;
  metric4?: number;
  metric5?: number;
  metric6?: number;
  metric7?: number;
  metric8?: number;
  metric9?: number;
  metric10?: number;
  metric11?: number;
  metric12?: number;
  metric13?: number;
  metric14?: number;
  metric15?: number;
  metric16?: number;
  metric17?: number;
  metric18?: number;
  metric19?: number;
  metric20?: number;
}

export interface ITelemetrySession {
  instance?: Telemetry;
  logEvent: (options: {
      category: string;
      action: string;
      label?: string;
      details?: string;
      dimensions?: string[];
      metrics?: number[];
  }) => void;
  enabled: boolean;
}

export interface ITelemetryOptions {
  name: string;
  version: string;
  dev?: IAmazonTelemetryOptions;
  prod?: IAmazonTelemetryOptions;
  qa?: IAmazonTelemetryOptions;
}

export interface IAmazonTelemetryOptions {
  amazon: {
      userPoolID: string;
      app: { id: string; };
  };
}

export interface IAppConfig {
  agolPortalUrl: string;
  anonAgolSession?: UserSession;
  authentication?: Auth;
  agoBasedEnterpriseSolutionsGroupId: string;
  appId: string;
  diagramKey: string;
  isEnterprise: boolean;
  languageDirection?: "ltr" | "rtl";
  languageResource?: string;
  locale: string;
  orgUrl: string;
  page?: IAppPage;
  portalURL: string;
  primarySolutionsGroupId: string;
  userSession?: UserSession;
  allCards: ISolutionInfoCard[];
  telemetrySession?: ITelemetrySession;
  measurementIds?: string[];
  cookiesFirstUseVar?: string;
  trackingEnabled?: boolean;
  forceTrackingEnv?: TEnvironments | "";
  telemetry?: ITelemetryOptions;
  v1SolutionId?: string;
  queryParams?: IQueryParams;
}

export interface IAppPage {
  pageType: DeployAppTab;
  solutionTitleOrId?: string;
}

export interface IAppPageInit {
  page: IAppPage;
  v1SolutionId?: string;
  queryParams: IQueryParams;
}

export interface IQueryParams {
  domain: string | null;
  industry: string | null;
  locale: string;
  offerType: string | null;
  searchTerm: string | null;
  sortField: string | null;
  signInParam: string | null;
}

export const EOfferType: {
    BOTH: string;
    NEW: string;
    SUGGESTED: string;
};

export const ESortField: {
    NEW: string;
    NUMVIEWS: string;
    RELEVANCE: string;
    SUGGESTED: string;
    TITLE: string;
    UPDATED: string;
};

export const ESignInParam: {
    DEPLOY: string;
    AIOPEN: string;
};

export interface IQuickLink {
  icon: Icon["icon"];
  label: string;
  url: string;
}

export interface INavTab {
  tabType: DeployAppTab;
  card?: ISolutionInfoCard;
}

export interface IDeployCard {
  card: ISolutionInfoCard;
  cardRef?: SolutionDeployedCard;
}

export interface IDeployingCarouselMessage {
  message: string;
  url?: string;
  icon?: Icon["icon"];
}

export interface IOrgSettings {
  aiAssistantsEnabled?: boolean;
  blockBetaApps?: boolean;
  colocateCompute?: boolean;
}

export interface ResourceCard {
  icon?: string;
  meridianIcon?: string;
  heading: string;
  description: string;
  url?: string;
}

export interface IDeployCardFetchFailed {
  title: string;
  message: string;
}