import { BehaviorSubject, Subject } from 'rxjs'
import { filter, map } from 'rxjs/operators'
import autobind from 'autobind-decorator'

import { createFormObservable } from './factory'

export class FormObservable extends Subject {
  static EVENT = 'submit'

  input$
  onError
  hasError

  constructor(input$, onError = (error) => {}, formElement) {
    super()

    this.input$ = input$
    this.onError = onError
    this.hasError = false

    if (formElement) {
      this.init(formElement)
    }

    this.handleFormSubmit = this.handleFormSubmit.bind(this);
  }


  handleFormSubmit(event) {
    event.preventDefault()
    let errorObject = {}
    const inputValues = this.input$.getValue()
    this.hasError = false

    const formValue = Object.keys(inputValues).reduce((obj, fieldName) => {
      if (inputValues[fieldName].error) {
        this.hasError = true

        errorObject = {
          ...errorObject,
          [fieldName]: inputValues[fieldName].error,
        }
      }

      return {
        ...obj,
        [fieldName]: inputValues[fieldName].value,
      }
    }, {})

    if (this.hasError) {
      this.onError(errorObject)
    }

    return formValue
  }

  init(element) {
    return createFormObservable({ element, event: FormObservable.EVENT })
      .pipe(map(this.handleFormSubmit), filter(() => !this.hasError))
      .subscribe(this.next.bind(this))
  }
}
