/* eslint-disable @typescript-eslint/unified-signatures */
import { HttpStep, IHttpStep } from '../../HttpStep.js'

export const SetDataStepKind = 'HttpAction#SetData'

/**
 * Sets a manually defined value that can be passed to the next step.
 */
export interface ISetDataStep extends IHttpStep {
  kind: typeof SetDataStepKind
  /**
   * The value to return to the next step.
   * This is always a string. Use the `dataType` to determine the correct data type.
   */
  value: string
  /**
   * The data type of the value. This is a value prefixed with
   * `http://www.w3.org/2001/XMLSchema#` or `http://a.ml/vocabularies/shapes#`.
   *
   * Examples:
   *
   * - `http://www.w3.org/2001/XMLSchema#boolean`
   * - `http://www.w3.org/2001/XMLSchema#string`
   * - `http://www.w3.org/2001/XMLSchema#number`
   * - `http://www.w3.org/2001/XMLSchema#integer`
   * - `http://www.w3.org/2001/XMLSchema#long`
   * - `http://a.ml/vocabularies/shapes#number`
   * - `http://a.ml/vocabularies/shapes#integer`
   * - `http://a.ml/vocabularies/shapes#double`
   * - ...
   *
   * @default `http://www.w3.org/2001/XMLSchema#string`
   */
  dataType?: string
}

export class SetDataStep extends HttpStep {
  override kind = SetDataStepKind

  /**
   * The value to return to the next step.
   * This is always a string. Use the `dataType` to determine the correct data type.
   */
  value = ''

  /**
   * The data type of the value. This is a value prefixed with
   * `http://www.w3.org/2001/XMLSchema#` or `http://a.ml/vocabularies/shapes#`.
   *
   * Examples:
   *
   * - `http://www.w3.org/2001/XMLSchema#boolean`
   * - `http://www.w3.org/2001/XMLSchema#string`
   * - `http://www.w3.org/2001/XMLSchema#number`
   * - `http://www.w3.org/2001/XMLSchema#integer`
   * - `http://www.w3.org/2001/XMLSchema#long`
   * - `http://a.ml/vocabularies/shapes#number`
   * - `http://a.ml/vocabularies/shapes#integer`
   * - `http://a.ml/vocabularies/shapes#double`
   * - ...
   *
   * @default `http://www.w3.org/2001/XMLSchema#string`
   */
  dataType?: string

  /**
   * Creates the step from values.
   * @param value The value this step sets.
   * @param dataType The data type to use to read the value.
   */
  constructor(value: string, dataType?: string)

  /**
   * Creates the step from serialized schema.
   * @param init The serialized step values.
   */
  constructor(init: ISetDataStep)

  /**
   * Creates an empty step.
   */
  constructor()

  constructor(valueOrInit?: string | ISetDataStep, dataType?: string) {
    super()
    if (!valueOrInit) {
      return
    }
    if (typeof valueOrInit === 'object') {
      const typed = valueOrInit as ISetDataStep
      this.new(typed)
    } else if (typeof valueOrInit === 'string') {
      this.new({
        kind: SetDataStepKind,
        value: valueOrInit,
        dataType,
        enabled: true,
      })
    }
  }

  override new(init: ISetDataStep): void {
    super.new(init)
    this.kind = SetDataStepKind
    this.value = init.value
    this.dataType = init.dataType
  }

  checkValidity(): boolean {
    const { value } = this
    return !!value
  }

  override toJSON(): ISetDataStep {
    const result: ISetDataStep = {
      ...super.toJSON(),
      kind: SetDataStepKind,
      value: this.value,
    }
    if (this.dataType) {
      result.dataType = this.dataType
    }
    return result
  }
}
