import realFaceModes, { RealFaceMode } from './environment/realFaceModes';
import { DocumentTypeName } from './environment/documentTypes';
import { StepType } from './environment/stepsDescription';
import { AllLabels, supportedLanguages } from './environment/langs';
import { ModalPositionKeys, modalPositions } from './environment/modalPosition';
import { MessageAfterDelay } from './types/core/MessageAfterDelay';
import { DeepPartial } from './types/helpers/DeepPartial';

export type ValidationFn =
  'validateElement'
  | 'validateString'
  | 'validateDocumentTypes'
  | 'validateDistinctStringInArray'
  | 'validateNumber'
  | 'validateFunction'
  | 'ValidateDictionaryLangMatch'
  | 'validateBool'
  | 'validateAllowCameraSelection';
type DefaultValueFunction = () => boolean;
export type NormalizedType = 'Path';

/**
 * { boolean? } uploader
 * { boolean? } video
 */
export type StepMode = {
  uploader?: boolean,
  video?: boolean,
};
export type IStepModeKeys = keyof StepMode;
export type StepConfig = {
  type: StepType,
  name: string,
  mode: StepMode,
  autocaptureDelay?: number,
  enableDesktopNotification?: boolean,
  enableFourCornerCapture?: boolean,
  shouldRecordMultiImages?: boolean,
  delayUntilCaptureButtonVisible?: number,
  messageAfterDelay?: MessageAfterDelay,
};

export type DocumentType = {
  type: DocumentTypeName,
  steps: StepConfig[],
  mode?: StepMode,
  tooltipText?: string,
};

type ImageURI = 'png' | 'jpeg' | 'webp';

export type DefaultConfigName = 'el'
| 'licenseKey'
| 'networkUrl'
| 'language'
| 'customTranslations'
| 'documentTypes'
| 'realFaceMode'
| 'modalPosition'
| 'resizeUploadedImage'
| 'showSubmitBtn'
| 'isShowDocumentTypeSelect'
| 'useCDN'
| 'processingImageFormat'
| 'allowSubmitWithWarnings'
| 'autocaptureConfidence'
| 'autoContinue'
| 'autoStart'
| 'playPreviewAnimations'
| 'autocaptureDelay'
| 'fixFrontOrientAfterUpload'
// | 'captureTimeout'
// | 'onCaptureTimeout'
| 'onChange'
| 'onReset'
| 'submit'
| 'onRetakeHook'
| 'onCameraError'
| 'onMounted'
| 'onDocumentTypeSelect'
| 'onReloaded'
| 'allowCameraSelection';

/**
 * IDefaultConfig
 * @param {string} name,
 * @param {'String' | 'Array' | 'Number' | 'Boolean' | 'Function' | 'Object'}  type,
 * @param {string} description,
 * @param {string | boolean | DefaultValueFunction | number | DocumentType[] | MessageAfterDelay} defaultValue,
 * @param {ValidationFn}  validationFn,
 * @parma {boolean} hidden?,
 * @param {RealFaceMode[]} values?,
 * @param {any[]} arrayValues,
 * @param {boolean} multiple?,
 */
export interface IDefaultConfig {
  name: DefaultConfigName,
  type: 'String' | 'Array' | 'Number' | 'Boolean' | 'Function' | 'Object',
  description: string,
  defaultValue: StepMode | string | boolean | DefaultValueFunction | number | DocumentType[] | MessageAfterDelay,
  validationFn: ValidationFn,
  hidden?: boolean,
  values?: ModalPositionKeys[] | RealFaceMode[] | typeof supportedLanguages[number][] | ImageURI[] | DeepPartial<AllLabels>,
  arrayValues?: unknown[],
  multiple?: boolean,
  normalizedType?: NormalizedType,
}

/**
 * @param {String} name - config param name
 * @param {any} defaultValue - value to fallback
 * @param {String} validationFn - name of validation function from Config module
 */
const defaultConfig: IDefaultConfig[] = [
  {
    name: 'el',
    type: 'String',
    description: 'Id of an element on the page where the component will be integrated.',
    defaultValue: 'videoCapturingEl',
    validationFn: 'validateElement',
  },
  {
    name: 'licenseKey',
    type: 'String',
    description: 'Key for the library',
    defaultValue: '',
    validationFn: 'validateString',
  },
  {
    name: 'onDocumentTypeSelect',
    type: 'Function',
    description: 'Callback-function which will be called after change type of document',
    defaultValue() {
      return true;
    },
    validationFn: 'validateFunction',
  },
  {
    name: 'networkUrl',
    type: 'String',
    description: 'Path to the folder with neural networks. Specify the path on the server if you need to remove the folder to another location. The default path is \'networks\'.',
    defaultValue: 'networks/',
    validationFn: 'validateString',
    normalizedType: 'Path',
  },
  {
    name: 'language',
    values: Array.from(supportedLanguages),
    type: 'Array',
    description: 'The option sets the language used for the translation of the text in the library',
    defaultValue: 'en',
    validationFn: 'validateDistinctStringInArray',
    arrayValues: Array.from(supportedLanguages),
    multiple: false,
  },
  {
    name: 'customTranslations',
    type: 'Object',
    defaultValue: {},
    description: '',
    validationFn: 'ValidateDictionaryLangMatch',
  },
  {
    name: 'documentTypes',
    type: 'Array',
    description: 'The option that describes what steps needs for each document type you are needed',
    defaultValue: [{
      type: 'DL',
      steps: [
        {
          type: 'front',
          name: 'Document Front',
          mode: {
            uploader: true,
            video: true,
          },
        },
        {
          type: 'pdf',
          name: 'Document PDF417 Barcode',
          mode: {
            uploader: true,
            video: true,
          },
        },
        {
          type: 'face',
          name: 'Face',
          mode: {
            uploader: true,
            video: true,
          },
        },
      ],
    }],
    validationFn: 'validateDocumentTypes',
  },
  {
    name: 'realFaceMode',
    values: ['auto', 'none', 'all'],
    type: 'Array',
    description: 'Option that enable advanced capture with volumetric face detection. Available values: \'auto\', \'none\'. Auto - enable "realFaceMode" only for iphone. All - enable "realFaceMode" for all devices. None - disable this option.',
    defaultValue: 'auto',
    validationFn: 'validateDistinctStringInArray',
    arrayValues: Object.keys(realFaceModes),
    multiple: false,
  },
  {
    name: 'modalPosition',
    type: 'Array',
    description: 'Place the document type selection modal inside the component.',
    defaultValue: 'center',
    validationFn: 'validateDistinctStringInArray',
    arrayValues: Object.keys(modalPositions),
    multiple: false,
  },
  {
    name: 'resizeUploadedImage',
    type: 'Number',
    description: 'Sets the maximum size for manually loaded pictures.',
    defaultValue: -1,
    validationFn: 'validateNumber',
  },
  {
    name: 'showSubmitBtn',
    type: 'Boolean',
    description: 'This option enables/disables the "submit" button after capturing all the images',
    defaultValue: true,
    hidden: true,
    validationFn: 'validateBool',
  },
  {
    name: 'isShowDocumentTypeSelect',
    type: 'Boolean',
    description: 'If this option is disabled, the library starts immediately with first configured document type.',
    defaultValue: true,
    validationFn: 'validateBool',
  },
  {
    name: 'useCDN',
    type: 'Boolean',
    description: 'Set to true if you prefer to load neural networks from cdn instead of your domain.',
    defaultValue: false,
    validationFn: 'validateBool',
  },
  {
    name: 'allowSubmitWithWarnings',
    type: 'Boolean',
    description: 'This option allows the user to perform a \'submit\' even if there are warnings',
    defaultValue: false,
    validationFn: 'validateBool',
  },
  {
    name: 'autocaptureConfidence',
    type: 'Number',
    description: 'This option allows the user to change autocapture prediction filter confidence',
    defaultValue: 0.8,
    validationFn: 'validateNumber',
  },
  {
    name: 'processingImageFormat',
    values: ['jpeg', 'png', 'webp'],
    type: 'Array',
    description: 'This option switches image format, that used for image processing',
    defaultValue: 'webp',
    validationFn: 'validateDistinctStringInArray',
    arrayValues: ['jpeg', 'png', 'webp'],
    multiple: false,
  },
  {
    name: 'autoContinue',
    type: 'Boolean',
    description: 'This option switches on/off the automatic transition to the next step.',
    defaultValue: true,
    validationFn: 'validateBool',
  },
  {
    name: 'autoStart',
    type: 'Boolean',
    description: 'This option allows you not to display the step selection screen when selecting a document.',
    defaultValue: false,
    validationFn: 'validateBool',
  },
  {
    name: 'playPreviewAnimations',
    type: 'Boolean',
    description: 'This option allows you to turn off step preview animations.',
    defaultValue: true,
    validationFn: 'validateBool',
  },
  {
    name: 'autocaptureDelay',
    type: 'Number',
    description: 'This option sets the delay (in ms) when automatically switching steps.',
    defaultValue: 1000,
    validationFn: 'validateNumber',
  },
  {
    name: 'fixFrontOrientAfterUpload',
    type: 'Boolean',
    description: 'This option provides the possibility to adjust the correct position of the document in case of manual uploading.',
    defaultValue: false,
    validationFn: 'validateBool',
  },
  // {
  //   name: 'captureTimeout',
  //   type: 'Number',
  //   description: 'This option allows you to set a timer in seconds, how long after the start of video capture the hook \'onCaptureTimeout\' will be triggered.',
  //   defaultValue: 0,
  //   validationFn: 'validateNumber',
  // },
  // {
  //   name: 'onCaptureTimeout',
  //   type: 'Function',
  //   description: 'Callback-function which will be called after the user failed to capture the document from the camera in the time specified by the \'captureTimeout\' option',
  //   defaultValue() {
  //     return true;
  //   },
  //   validationFn: 'validateFunction',
  // },
  {
    name: 'onChange',
    type: 'Function',
    description: 'Callback-function which will be called after change one step. The returnable value is the object with the type and the image',
    defaultValue() {
      return true;
    },
    validationFn: 'validateFunction',
  },
  {
    name: 'onReset',
    type: 'Function',
    description: 'Callback-function which will be called after reset all the steps. The returnable value is the object with the steps',
    defaultValue() {
      return true;
    },
    validationFn: 'validateFunction',
  },
  {
    name: 'submit',
    type: 'Function',
    description: 'Callback-function which will be called after completing all the steps.',
    defaultValue() {
      return true;
    },
    validationFn: 'validateFunction',
  },
  {
    name: 'onRetakeHook',
    type: 'Function',
    description: 'The function that will be called before reset the current step. The returnable value is the object with the current step',
    defaultValue() {
      return true;
    },
    validationFn: 'validateFunction',
  },
  {
    name: 'onCameraError',
    type: 'Function',
    description: 'The function that is invoked in case if the camera is not available. The response value is the object with the error code and the message',
    defaultValue() {
      return true;
    },
    validationFn: 'validateFunction',
  },
  {
    name: 'onMounted',
    type: 'Function',
    description: 'the function that will be called on the component mounted. This function doesn\'t return a value.',
    defaultValue() {
      return true;
    },
    validationFn: 'validateFunction',
  },
  {
    name: 'onReloaded',
    type: 'Function',
    description: 'Callback-function which will be called on the start component reloading',
    defaultValue() {
      return true;
    },
    validationFn: 'validateFunction',
  },
  {
    name: 'allowCameraSelection',
    type: 'Boolean',
    description: 'Allows manual camera source selection on desktop only; if false, the camera is chosen automatically.',
    defaultValue: false,
    validationFn: 'validateAllowCameraSelection',
  },
];

export default defaultConfig;
