import * as React from 'react'
import { connect } from 'react-redux'
import { FormFieldWrapper, BaseFormField } from '.'
import { FORM_REDUCER_KEY } from '../reducers'
import { mapStateToField } from '../selectors'
import {
    PhoneInputProps,
    PhoneInputComponentProps,
} from '../interfaces'
import { setFormField } from '../actions'
import {
    PhoneNumberUtil,
    PhoneNumberFormat,
    PhoneNumber,
} from 'google-libphonenumber'

const styles = require('../../src/styles/components/forms.scss')

class _PhoneInput extends BaseFormField<string> {

    private countryCode = 'GB'
    private phone: any
    private numberFormat: any

    constructor(props: PhoneInputComponentProps) {
        super(props)
        this.phone = PhoneNumberUtil.getInstance()
        this.numberFormat = PhoneNumberFormat.INTERNATIONAL
    }

    public componentDidMount() {
        this.dispatchUpdate(this.getNextFieldState(this.format(this.getValueFromState())))
    }

    public renderField() {
        const { name, disabled, placeholder } = this.props
        return (
            <input
                ref={this.setFieldRef}
                className={this.classNames()}
                name={name}
                id={`${name}Field`}
                placeholder={placeholder}
                type="text"
                value={this.getValueFromState()}
                disabled={disabled}
                onChange={this.onChange}
                onFocus={this.onFocus}
                onBlur={this.onBlur} />
        )
    }
    /**
     * TODO - this function is inefficient
     * because it parses the value for a second time to validate
     * It's been left in here because of the way the BaseForm component
     * works but really it should be given a parsed value
     * Also the fact that the min chars check is repeated
     * Yes... this is definitely some shit code. Ooops. Sorry :)
     * @param value
     */
    public validate(value: string) {
        if (!value) {
            return this.props.field.required ? ['* required'] : []
        } else if (value.length > 3) {
            const parsed = this.parse(value)
            if (parsed && this.phone.isValidNumber(parsed)) {
                return []
            }
        }
        return ['* not a valid UK number']
    }

    public getValueFromEvent(e: React.SyntheticEvent<any>) {
        return this.format(e.currentTarget.value)
    }

    /**
     * Format the phone number in international format
     * Google only allow phone numbers with more
     * than 3 digits to be parsed
     *
     * @param e
     */
    private format(value: string) {
        if (value.length > 3) {
            const parsed = this.parse(value)
            if (parsed) {
                return this.phone.format(parsed, this.numberFormat)
            }

        }
        return value
    }

    /**
     * Transform string input into an
     * object of type PhoneNumber
     *
     * @param value
     */
    private parse(value: string): PhoneNumber | undefined {
        try {
            return this.phone.parse(value, this.countryCode)
        } catch (e) {
            return undefined
        }
    }
}

const mapStateToProps = (state: any, ownProps: PhoneInputProps) => ({
    ...ownProps,
    field: mapStateToField(state[FORM_REDUCER_KEY], ownProps),
})

const mapDispatchToProps = {
    setFormField,
}

const ConnectedPhoneInput = connect(mapStateToProps, mapDispatchToProps)(_PhoneInput)

export class PhoneInput extends FormFieldWrapper<PhoneInputProps> {
    public render() {
        return (
            <ConnectedPhoneInput {...this.props} formName={this.formName} />
        )
    }
}
