import isPromise from 'is-promise';
import FormConnector from './FormConnector'
import StoreFactory from './helpers/FormStoreFactory';
import FormActions from './helpers/FormActions';
import Utils from './helpers/FormUtils';

const Namespaces = Utils.Namespaces()

export { FormConnector, Namespaces }

export default (namespace, dispatcher, opts) => {
  Namespaces.register(namespace);

  const {
    initialState={},
    onSubmit= s => s,
    onSubmitSuccess= s => s,
    onSubmitFail= e => e,
    fields={},
    normalizers={},
  } = opts

  // get the action creators
  const {
    changed, saved, canceled,
    validationStarted, validationFailed,
    focused, blurred, normalized,
    submitSuccess, submitFailed, startLoading,
    endLoading
  } = FormActions(namespace)

  const store = StoreFactory(namespace, dispatcher, initialState)

  const submit = (e) => {
    if (typeof e === 'object' && typeof e.preventDefault === 'function') {
      e.preventDefault();
    }

    dispatcher.dispatch(startLoading()); // update load state
    normalize();
    return validate()
      .then(state => {
        dispatcher.dispatch(saved(state));
        let response = onSubmit(state);

        if (isPromise(response)) {
          return response
            .then((response) => {
              dispatcher.dispatch(submitSuccess());
              dispatcher.dispatch(endLoading());
              onSubmitSuccess(response)
            }).catch((response) => {
              dispatcher.dispatch(submitFailed(response));
              dispatcher.dispatch(endLoading());
              onSubmitFail(response)
            });
        } else {
          dispatcher.dispatch(endLoading());
          return Promise.resolve(response);
        }
      }).catch((err) => {
        dispatcher.dispatch(endLoading());
        return err;
      })
  }

  const validate = () => {
    dispatcher.dispatch(validationStarted());
    let currentState = store.getState().fields;
    let validators = fields;
    return Utils.validate(currentState, fields).catch(errors => {
      dispatcher.dispatch(validationFailed(errors));
      return Promise.reject(errors);
    })
  }

  const normalize = () => {
    let currentState = store.getState().fields;
    let normalizedState = Utils.normalize(currentState, normalizers)
    dispatcher.dispatch(normalized(normalizedState));
    return normalizedState;
  }

  const cancel = () => {
    let currentState = store.getState().fields;
    dispatcher.dispatch(canceled(currentState));
    dispatcher.dispatch(endLoading());
  }

  const onChange = (ev) => { Utils.dispatchEvent(ev, change) }
  const change = (state) => {
    let currentState = store.getState().fields;
    let newState = Object.assign({}, currentState, state)
    let changedKey = Object.keys(state)[0];
    dispatcher.dispatch(changed({state:newState, key:changedKey}));

    return Promise.resolve(newState);
  }

  const onBlur = (ev) => { Utils.dispatchEvent(ev, blur) }
  const blur = (state) => {
    let key = Object.keys(state)[0];
    let value = state[key];
    dispatcher.dispatch(blurred({key, value}))
  }

  const onFocus = (ev) => { Utils.dispatchEvent(ev, focus) }
  const focus = (state) => {
    let key = Object.keys(state)[0];
    let value = state[key];
    dispatcher.dispatch(focused({key, value}))
  }

  const formFields = () => {
    const state = store.getState().fields;
    return Object.keys(fields).reduce((all, key) => {
      let value = state[key] || '';
      all[key] = {'data-flux-key': key, value, onChange, onFocus, onBlur}
      return all;
    }, {})
  }

  return {
    store,
    submit,
    cancel,
    validate,
    normalize,
    change,
    blur,
    fields: formFields,
  }
}


@@ -522,17 +522,16 @@
 izers=%7B%7D
-,
 %0A  %7D = o
@@ -3032,36 +3032,8 @@
 0%5D;%0A
-    let value = state%5Bkey%5D;%0A
     
@@ -3058,37 +3058,42 @@
 h(blurred(%7Bkey, 
-value
+state%5Bkey%5D
 %7D))%0A  %7D%0A%0A  const
@@ -3216,36 +3216,8 @@
 0%5D;%0A
-    let value = state%5Bkey%5D;%0A
     
@@ -3236,21 +3236,21 @@
 ispatch(
-focus
+blurr
 ed(%7Bkey,
@@ -3250,21 +3250,26 @@
 d(%7Bkey, 
-value
+state%5Bkey%5D
 %7D))%0A  %7D%0A
@@ -3658,17 +3658,16 @@
 rmFields
-,
 %0A  %7D%0A%7D%0A%0A

fix up Form file