// Type definitions for DOIForms
// Project: DOIForms
// Definitions by: Idaho Edokpayi

import * as React from "react";
// interfaces
declare interface IButton {
  Field: IField;
  Value: FieldValue;
}
declare interface IButtonFieldsProps {
  CompareFields: CompareFieldsFunc;
  Fields: IField[];
}
declare interface IDOIFormAction {
  Action: EnumFormAction;
  Update?: IDOIFormState;
}
declare interface IDOIFormProps {
  CustomCSS?: React.CSSProperties;
  CustomFormLogic?: FormLogicFunc;
  ErrorHandler: ErrorHandlerFunc;
  Fields: Array<IField|IFileField|ISelectField>;
  Footer?: JSX.Element;
  FormTemplate: TemplateFormFunc;
  Header?: JSX.Element;
  RedirectURL?: string;
  ResetAction?: BasicActionFunc;
  SubmitAction: SubmitActionFunc;
  SubmitPage?: JSX.Element;
  FormAction?: FormActionFunc;
}
declare interface IDOIFormState {
  ErrorMessage?: string;
  ErrorStack?: string;
  FieldStates?: IFieldState[];
  HasError?: boolean;
  IsComplete?: boolean;
  IsValid?: boolean;
  Submitted?: boolean;
}
declare interface IField {
  ClassName?: string;
  Disabled?: boolean;
  DisplayName: string;
  FieldCustomization?: JSX.Element;
  Description?: string;
  Id: string;
  InitialValue?: FieldValue;
  Name: string;
  Order: number;
  Placeholder?: string;
  Required: boolean;
  Serialize?: SerializeFunc;
  Type: EnumFieldType;
  Validation?: ValidateFunc;
}
declare interface IFieldState {
  ErrorMessage?: string;
  Field: IField;
  Status: EnumFieldStatus;
  Value?: FieldValue;
}
declare interface IHandleChangeProps {
  Field: IField;
  SendMessage: FormActionFunc;
}
declare interface IInputControlProps {
  AriaDescribedBy: string;
  SendMessage: FormActionFunc;
  FeedbackElement: JSX.Element;
  Field: IField;
  Value: FieldValue;
}
declare interface IOption {
  Value?: FieldValue;
  Text: string;
}
declare interface IResetActionHandlerProps {
  ResetAction?: BasicActionFunc;
  FieldStateIterator: IterableIterator<IFieldState>;
  SetFieldState: SetFieldStateFunc;
}
declare interface IMultipleField extends IField{
  Multiple: boolean;
}
declare interface IFileField extends IMultipleField {
  Reference: React.RefObject<HTMLInputElement>;
}

declare interface ISelectField extends IMultipleField {
  Options: IOption[];
}
declare interface ISetupFieldStatesProps {
  CompareFields: CompareFieldsFunc;
  Fields: IField[];
}
declare interface ITemplateFormProps {
  Buttons: IButton[];
  ErrorHandler: ErrorHandlerFunc;
  FieldStates: IFieldState[];
  Footer?: JSX.Element;
  HandleSubmit: (Event: React.FormEvent<HTMLFormElement>) => void;
  HandleReset: () => void;
  Header?: JSX.Element;
  IsError?: boolean;
  SendMessage: FormActionFunc;
  Styles: React.CSSProperties;
  SystemErrorMessage?: string;
}
declare interface IValidateProps {
  FieldStates: IterableIterator<IFieldState>;
}
declare interface IValidationResult {
  IsError: boolean;
  Message?: string;
}
declare type BasicActionFunc = () => void;
declare type ChangeEventHandler<T> = (event: React.ChangeEvent<T>) => void;
declare type CompareFieldsFunc = (a: IField, b: IField) => number;
declare type ErrorHandlerFunc = (
  ErrorMessage?: string,
  Stack?: string
) => JSX.Element;
declare type FormActionFunc = (action: IDOIFormAction) => void;
declare type FormSerializeFunction = () => string;
declare type FormLogicFunc = (
  state: IDOIFormState,
  action: IDOIFormAction
) => IDOIFormState;
declare type InputControlFunc<T> = (props: IInputControlProps) => JSX.Element;
declare type JSONSerialize = () => any;
declare type SerializeFunc = (fieldState: IFieldState) => string;
declare type SetFieldStateFunc = (id: string, fieldState: IFieldState) => void;
declare type SetupFieldStatesFunc = (
  props: ISetupFieldStatesProps
) => IFieldState[];
declare type SubmitActionFunc = (
  FieldStates: IFieldState[],
  FormSerialize: FormSerializeFunction,
  JSONSerializer: JSONSerialize
) => Promise<void>;
declare type TemplateFormFunc = (props: ITemplateFormProps) => JSX.Element;
declare type ValidateFunc = (value: FieldValue) => IValidationResult;
declare type FieldValue = string|number|Date|boolean;

// enumerations
declare enum EnumFieldStatus {
  Initial = 0,
  Modified = 1,
  Error = 2,
  Empty = 3
}
declare enum EnumFieldType {
  color = 0,
  checkbox = 1,
  custom = 2,
  date = 3,
  datetime = 4,
  "datetime-local" = 5,
  email = 6,
  file = 7,
  month = 8,
  number = 9,
  password = 10,
  radio = 11,
  range = 12,
  reset = 13,
  search = 14,
  select = 15,
  submit = 16,
  tel = 17,
  text = 18,
  textarea = 19,
  time = 20,
  url = 21,
  week = 22
}
declare enum EnumFormAction {
  NoOp = 0,
  Submit = 1,
  Reset = 2,
  Update = 3,
  HandleError = 4
}
declare class DOIFormComponent extends React.Component<
  IDOIFormProps,
  IDOIFormState
> {
  private handleSubmitFunction;
  private handleResetFunction;
  private sendMessageFunction;
  constructor(props: IDOIFormProps);
  componentDidCatch(Error: Error, ErrorInfo: React.ErrorInfo): void;
  render(): React.ReactNode;
  HandleSubmit(Event: React.FormEvent<HTMLFormElement>): void;
  HandleReset(): void;
  SendMessage(action: IDOIFormAction): void;
  Styles(): React.CSSProperties;
  FormLogic(action: IDOIFormAction): void;
  RenderError(): JSX.Element;
  RenderForm(): JSX.Element;
}
export {
  // class
  DOIFormComponent,
  // enumerations
  EnumFieldStatus,
  EnumFieldType,
  EnumFormAction,
  // interfaces
  IButton,
  IButtonFieldsProps,
  IDOIFormAction,
  IDOIFormProps,
  IDOIFormState,
  IField,
  IMultipleField,
  IFileField,
  IFieldState,
  IHandleChangeProps,
  IInputControlProps,
  IOption,
  IResetActionHandlerProps,
  ISelectField,
  ISetupFieldStatesProps,
  ITemplateFormProps,
  IValidateProps,
  IValidationResult,
  // types
  BasicActionFunc,
  ChangeEventHandler,
  CompareFieldsFunc,
  ErrorHandlerFunc,
  FieldValue,
  FormActionFunc,
  FormLogicFunc,
  FormSerializeFunction,
  InputControlFunc,
  JSONSerialize,
  SerializeFunc,
  SetFieldStateFunc,
  SetupFieldStatesFunc,
  SubmitActionFunc,
  TemplateFormFunc,
  ValidateFunc
};
