import React from 'react';
import { ModelListener } from 'front';
import { matcher } from '../../etc/util';
import AutoComplete from '../../atoms/auto-complete/auto-complete.jsx';
import TextInput from '../../atoms/text-input/text-input.jsx';
import TextArea from '../../atoms/text-area/text-area.jsx';
import PostalCode from '../../atoms/postal-code/postal-code.jsx';
import Dropdown from '../../atoms/dropdown/dropdown.jsx';
import AddressModel from './address.js';
import { FormValidation } from '../../transforms';
import { createSyncChecker } from '../../transforms/form-validation';
import '../../less/grid.less';

/**\

    title: Address
    category: component
    description: A standard address form with an autocomplete field
    props:
        label[String|null]:
            The label for component. default is "Address". Set to null
            to not show any label.
        lock[Boolean]:
            Disable city & state until zip code is entered, since it
            auto-populates city & state. default is true.
        abbreviated[Boolean]:
            Use abbreviated state names. default is false.
        withNotes[Boolean]:
            Toggles the display of a big text area underneath the
            address fields for location specific notes. default is false.
        native[Boolean]:
            whether the dropdown for state selection uses native select/option

\**/
class Address extends ModelListener {
    static defaultProps = {
        model: AddressModel,
        lock: true,
        withNotes: false,
        abbreviated: false
    };

    static defaultErrorMessages = {
        street: 'Enter the street address.',
        city: 'Enter the city.',
        state: 'Select a state.',
        zip: 'Enter the zip code.',
        country: 'Select a country.'
    };

    static makeFieldValidator = function(errorMessages) {
        const getErrorMessage = matcher(
            errorMessages,
            Address.defaultErrorMessages,
            null);

        return function(fieldname, value) {
            switch (fieldname) {
                case 'street':
                case 'city':
                case 'state':
                case 'country':
                    if (!value) {
                        return getErrorMessage(fieldname);
                    }
                    break;
                case 'zip':
                    if (!PostalCode.validate(value)) {
                        return getErrorMessage(fieldname);
                    }
                    break;
                default:
                    return null;
            }

            return null;
        };
    };

    state = {
        locked: false // city/state inputs disabled when true
    };

    constructor(props) {
        super(props);

        FormValidation(
            this,
            createSyncChecker(this, Address.makeFieldValidator())
        );

        this.state.locked = props.lock;
    }

    fill(address) {
        for (const key in address) {
            // use update to clear errors for now-valid fields
            this.update(key, address[key]);
        }
        this.unlock();
    }

    unlock() {
        this.setState({
            locked: false
        });
    }

    // convenience method for updating error messages using
    // the default field validation logic
    setErrorMessages(errorMessages) {
        this.formValidate.settings.setChecker(
            createSyncChecker(this, Address.makeFieldValidator(errorMessages))
        );
    }

    render() {
        let notes, label, states;

        if (this.props.withNotes) {
            notes = (
                <div className="row t100">
                    <TextArea placeholder="Notes for the Postmate"
                        altPlaceholder="Callbox Number, Door Instructions, etc"
                        value={ this.model.notes }
                        update={ this.update.bind(this, 'notes') } />
                </div>
            );
        }

        if (this.props.label === undefined) {
            label = 'Address';
        } else {
            label = this.props.label;
        }

        if (this.props.abbreviated) {
            states = AddressModel.statesOptionsAbbrev;
        } else {
            states = AddressModel.statesOptions;
        }

        return (
            <div className="address-form">
                <div className="row t75-25">
                    <AutoComplete placeholder="Street Address"
                        altPlaceholder="Street Number and Name"
                        label={ label }
                        value={ this.model.street }
                        error={ this.model.errors.street }
                        match={ this.fill.bind(this) }
                        update={ this.update.bind(this, 'street') } />
                    <TextInput placeholder="Apt / Suite"
                        value={ this.model.apt }
                        error={ this.model.errors.apt }
                        update={ this.update.bind(this, 'apt') } />
                </div>
                <div className="row t25-50-25">
                    <PostalCode
                        value={ this.model.zip }
                        error={ this.model.errors.zip }
                        update={ this.update.bind(this, 'zip') }
                        failed={ this.unlock.bind(this) }
                        match={ this.fill.bind(this) } />
                    <TextInput placeholder="City"
                        value={ this.model.city }
                        error={ this.model.errors.city }
                        disabled={ this.state.locked }
                        update={ this.update.bind(this, 'city') } />
                    <Dropdown placeholder="State"
                        native={ this.props.native }
                        value={ this.model.state }
                        error={ this.model.errors.state }
                        items={ states }
                        disabled={ this.state.locked }
                        onSelect={
                            (option) => this.update('state', option.value)
                        } />
                </div>
                { notes }
            </div>
        );
    }
}

export default Address;
