import {type CapturedResultItem, EnumCapturedResultItemType} from "../core";
import type {BarcodeResultItem, DecodedBarcodesResult} from "../dbr";
import type {ParsedResult, ParsedResultItem} from "../dcp";
import type {RecognizedTextLinesResult, TextLineResultItem} from "../dlr";
import type {
  DetectedQuadResultItem,
  DeskewedImageResultItem,
  EnhancedImageResultItem,
  ProcessedDocumentResult
} from "../ddn";
import type {CapturedResultBase} from "../core/CapturedResultBase";

/**
 * The CapturedResult interface describes the basic structure of a result object returned by Dynamsoft Capture Vision Router({@link CaptureVisionRouter}).
 *
 * @remarks Depending on the functional module that generated the result item, the interface may vary:
 * - dynamsoft-barcode-reader: {@link DecodedBarcodesResult}
 * - dynamsoft-label-recognizer: {@link RecognizedTextLinesResult}
 * - dynamsoft-document-normalizer: {@link ProcessedDocumentResult}
 * - dynamsoft-code-parser: {@link ParsedResult}
 *
 * @see {@link CapturedResultReceiver.onCapturedResultReceived}
 * @see {@link CapturedResultBase}
 * */
export interface CapturedResult extends CapturedResultBase{
  /**
   * An array of CapturedResultItem objects representing the captured result items.
   * */
  items?: Array<CapturedResultItem>;

  /**Get a {@link DecodedBarcodesResult} object that contains all the {@link BarcodeResultItem} in this CapturedResult.*/
  decodedBarcodesResult?: DecodedBarcodesResult;

  /**Get a {@link RecognizedTextLinesResult} object that contains all the {@link TextLineResultItem} in this CapturedResult.*/
  recognizedTextLinesResult?: RecognizedTextLinesResult;

  /**Get a {@link ProcessedDocumentResult} object that contains all the {@link EnhancedImageResultItem} ,{@link DeskewedImageResultItem} and {@link DetectedQuadResultItem} in this CapturedResult.*/
  processingDocumentResult?: ProcessedDocumentResult;

  /**Get a {@link ParsedResult} object that contains all the {@link ParsedResultItem} in this CapturedResult.*/
  parsedResult?: ParsedResult;
}

/**@internal*/
export function _populateResults(result: CapturedResult | null | undefined) {
  if (result) {
    result.decodedBarcodesResult = getDecodedBarcodesResult(result)
    result.recognizedTextLinesResult = getRecognizedTextLinesResult(result)
    result.processingDocumentResult = getProcessingDocumentResult(result)
    result.parsedResult = getParsedResult(result)
  }
}


/**@internal*/
function getDecodedBarcodesResult(result: CapturedResult): DecodedBarcodesResult {
  return {
    originalImageHashId: result.originalImageHashId,
    errorCode: result.errorCode,
    errorMessage: result.errorMessage,
    rotationTransformMatrix: result.rotationTransformMatrix,
    items: result.items?.filter(item => {
      return item.type == EnumCapturedResultItemType.CRIT_BARCODE
    }).map(item => {
      return item as BarcodeResultItem
    })

  } as DecodedBarcodesResult;
}

/**@internal*/
function getRecognizedTextLinesResult(result: CapturedResult): RecognizedTextLinesResult {
  return {
    originalImageHashId: result.originalImageHashId,
    errorCode: result.errorCode,
    errorMessage: result.errorMessage,
    rotationTransformMatrix: result.rotationTransformMatrix,
    items: result.items?.filter(item => {
      return item.type == EnumCapturedResultItemType.CRIT_TEXT_LINE
    }).map(item => {
      return item as TextLineResultItem
    })
  } as RecognizedTextLinesResult;
}

/**@internal*/
function getProcessingDocumentResult(result: CapturedResult): ProcessedDocumentResult {
  return {
    originalImageHashId: result.originalImageHashId,
    errorCode: result.errorCode,
    errorMessage: result.errorMessage,
    rotationTransformMatrix: result.rotationTransformMatrix,
    deskewedImageResultItems: result.items?.filter(item => {
      return item.type == EnumCapturedResultItemType.CRIT_DESKEWED_IMAGE
    }).map(item => {
      return item as DeskewedImageResultItem
    }),
    detectedQuadResultItems: result.items?.filter(item => {
      return item.type == EnumCapturedResultItemType.CRIT_DETECTED_QUAD
    }).map(item => {
      return item as DetectedQuadResultItem
    }),
    enhancedImageResultItems: result.items?.filter(item => {
      return item.type == EnumCapturedResultItemType.CRIT_ENHANCED_IMAGE
    }).map(item => {
      return item as EnhancedImageResultItem
    })
  } as ProcessedDocumentResult;
}

/**@internal*/
function getParsedResult(result: CapturedResult): ParsedResult {
  return {
    originalImageHashId: result.originalImageHashId,
    errorCode: result.errorCode,
    errorMessage: result.errorMessage,
    items: result.items?.filter(item => {
      return item.type == EnumCapturedResultItemType.CRIT_PARSED_RESULT
    }).map(item => {
      return item as ParsedResultItem
    })
  } as ParsedResult;
}
