import * as React from 'react'
import { resetForm, destroyForm, submitFormValid, submitFormInvalid } from '../actions'
import { FormProps, FormModel, FormComponentProps, FormContext } from '../interfaces'
import { getForm } from '../selectors'
import { connect } from 'react-redux'
import * as PropTypes from 'prop-types'

class FormComponent extends React.Component<FormComponentProps, any> {

    public static childContextTypes = {
        formName: PropTypes.string,
    }

    public componentWillUnmount() {
        this.props.destroyForm(this.props.name)
    }

    /**
     * Make the form name available to child components
     * without explicitly passing it down to every one
     */
    public getChildContext(): FormContext {
        return {
            formName: this.props.name,
        }
    }

    /**
     * Render a form tag
     */
    public render() {

        const { name, id, children, className, style } = this.props

        return (
            <form
                name={name}
                id={id}
                className={className}
                style={style}
                onSubmit={this.onSubmit}>
                {children}
            </form>
        )
    }

    /**
     * Prevent the native onSubmit event from triggering
     * @param e
     */
    private onSubmit = (e: React.SyntheticEvent<any>) => {
        e.preventDefault()

        const { formData, name, onSubmit, submitFormValid, submitFormInvalid } = this.props

        const keys = Object.keys(formData)

        for (const field of keys) {
            if (formData[field] && !formData[field].valid) {
                // dispatch an action to say the form is submitted but invalid
                // and end the submission process here
                return submitFormInvalid(name, formData)
            }
        }
        // dispatch an action to say the form is submitted and valid
        submitFormValid(name, formData)

        // now call the onsubmit handler with the data
        if (onSubmit) {
            onSubmit(formData)
        }
    }
}

const mapStateToProps = (state: any, ownProps: FormProps) => ({
    formData: getForm(state, ownProps.name),
})

const mapDispatchToProps = {
    resetForm,
    destroyForm,
    submitFormValid,
    submitFormInvalid,
}

export const Form = connect(mapStateToProps, mapDispatchToProps)(FormComponent)