import { recognizerLogger as logger } from '../configuration/LoggerConfig'
import * as InkModel from '../model/InkModel'
import * as RecognizerContext from '../model/RecognizerContext'
import Constants from '../configuration/Constants'
import { handleSuccess } from './RecognizerService'

/**
 * Triggers
 * @typedef {Object} Triggers
 * @property {Array<String>} exportContent Supported triggers for exporting content.
 * @property {Array<String>} [addStrokes] Supported triggers for adding strokes.
 */

/**
 * Recognizer info
 * @typedef {Object} RecognizerInfo
 * @property {Array<String>} types Supported recognition types (TEXT, MATH, SHAPE, MUSIC, ANALYZER).
 * @property {String} protocol Supported protocol (REST, WEBSOCKET).
 * @property {String} apiVersion Supported API version.
 * @property {Triggers} availableTriggers Supported triggers for this recognizer.
 */

/**
 * Recognizer callback
 * @typedef {function} RecognizerCallback
 * @param {Object} [err] Error
 * @param {Model} [model] Result
 * @param {...String} [types] Result types
 */

/**
 * Simple callback
 * @typedef {function} Callback
 * @param {Object} [err] Error
 * @param {Object} [res] Result
 */

/**
 * Recognition service entry point
 * @typedef {Object} Recognizer
 * @property {function} getInfo Get information about the supported configuration (protocol, type, apiVersion, ...).
 * @property {function} init Initialize recognition.
 * @property {function} clear Clear server context. Currently nothing to do there.
 * @property {function} close Close and free all resources that will no longer be used by the recognizer.
 * @property {function} [undo] Undo Undo the last done action.
 * @property {function} [redo] Redo Redo the previously undone action.
 * @property {function} [resize] Resize.
 * @property {function} [pointerEvents] Pointer Events.
 * @property {function} [addStrokes] Add strokes.
 * @property {function} [export_] Export content.
 * @property {function} [import_] Import content.
 * @property {function} [convert] Convert.
 * @property {function} [waitForIdle] Wait for idle.
 * @property {function} [setPenStyle] Set pen style.
 * @property {function} [setPenStyleClasses] Set pen style classes.
 * @property {function} [setTheme] Set theme.
 */

/**
 * Initialize recognition
 * @param {RecognizerContext} recognizerContext Current recognizer context
 * @param {Model} model Current model
 * @return {Promise}
 */
export function init (recognizerContext, model) {
  const modelRef = InkModel.resetModelPositions(model)
  logger.debug('Updated model', modelRef)
  const recognizerContextRef = RecognizerContext.updateRecognitionPositions(recognizerContext, modelRef.lastPositions)
  recognizerContextRef.initPromise = Promise.resolve(modelRef)
  return recognizerContextRef.initPromise
    .then((res) => {
      recognizerContextRef.initialized = true
      logger.debug('Updated recognizer context', recognizerContextRef)
      handleSuccess(recognizerContextRef.editor, res, Constants.EventType.LOADED)
      return res
    })
}

/**
 * Reset server context. Currently nothing to do there.
 * @param {RecognizerContext} recognizerContext Current recognizer context
 * @param {Model} model Current model
 * @return {Promise}
 */
export function reset (recognizerContext, model) {
  const modelRef = InkModel.resetModelPositions(model)
  logger.debug('Updated model', modelRef)
  const recognizerContextRef = RecognizerContext.updateRecognitionPositions(recognizerContext, modelRef.lastPositions)
  delete recognizerContextRef.instanceId
  logger.debug('Updated recognizer context', recognizerContextRef)
  return Promise.resolve({
    res: modelRef
  })
}

/**
 * Clear server context. Currently nothing to do there.
 * @param {RecognizerContext} recognizerContext Current recognizer context
 * @param {Model} model Current model
 * @return {Promise}
 */
export function clear (recognizerContext, model) {
  const modelRef = InkModel.clearModel(model)
  logger.debug('Updated model', modelRef)
  const recognizerContextRef = RecognizerContext.updateRecognitionPositions(recognizerContext, modelRef.lastPositions)
  delete recognizerContextRef.instanceId
  logger.debug('Updated recognizer context', recognizerContextRef)
  return Promise.resolve({
    err: undefined,
    res: modelRef,
    events: [Constants.EventType.CHANGED, Constants.EventType.EXPORTED, Constants.EventType.RENDERED]
  })
}

/**
 * Close and free all resources that will no longer be used by the recognizer.
 * @param {RecognizerContext} recognizerContext Current recognizer context
 * @param {Model} model Current model
 * @return {Promise}
 */
export function close (recognizerContext, model) {
  const recognizerContextRef = recognizerContext
  recognizerContextRef.initialized = false
  delete recognizerContextRef.instanceId
  return Promise.resolve(model)
}
