import React from 'react';
import TextInput from '../../atoms/text-input';
import PostalCode from '../../atoms/postal-code';
import { ModelListener } from 'front';
import CreditCardModel from './credit-card.js';
import FormValidation, { createSyncChecker }
    from '../../transforms/form-validation';
import { matcher } from '../../etc/util';
import '../../less/grid.less';

/**\

    title: CreditCard
    category: component
    description: A standard credit card form
    props:
        nickname[Boolean]:
            Adds a text field to allow entering a label for the card. Default
            is false.
        inlineErrors[Boolean]:
            Show inline errors for invalid fields. Default if false. Error
            messages can always be accessed through <CreditCard>.model.errors.

\**/
class CreditCard extends ModelListener {
    static defaultProps = {
        model: CreditCardModel
    };

    static defaultErrorMessages = {
        number: 'Enter a valid card number.',
        month: 'Invalid expiration date.',
        year: 'Invalid expiration date.',
        cvv: 'Enter a valid CVV.',
        zip: 'Enter a valid zip code.'
    };

    static makeFieldValidator = function(errorMessages) {
        const getErrorMessages = matcher(
            errorMessages,
            CreditCard.defaultErrorMessages,
            null);

        return function(fieldname, value) {
            switch (fieldname) {
                case 'number':
                    if (!CreditCardModel.checkValid(value)) {
                        return getErrorMessages(fieldname);
                    }
                    break;
                case 'month':
                case 'year':
                case 'cvv':
                    if (!value) {
                        return getErrorMessages(fieldname);
                    }
                    break;
                case 'zip':
                    if (!PostalCode.validate(value)) {
                        return getErrorMessages(fieldname);
                    }
                    break;
                default:
                    return null;
            }

            return null;
        };
    }

    constructor(props) {
        super(props);

        FormValidation(
            this,
            createSyncChecker(this, CreditCard.makeFieldValidator())
        );
    }

    setErrorMessages(errorMessages) {
        this.formValidate.settings.setChecker(
            createSyncChecker(
                this,
                CreditCard.makeFieldValidator(errorMessages))
        );
    }

    updateExpirationDate(date) {
        let _date = date;

        if (!_date) {
            _date = {
                month: null,
                year: null
            };
        }

        this.model.fill(_date);
    }

    render() {
        let nickname,
            expirationDate = null,
            errors = {};

        if (this.model.month && this.model.year) {
            expirationDate = {
                month: this.model.month,
                year: this.model.year
            };
        }

        if (this.props.inlineErrors) {
            errors = this.model.errors;
            errors.expirationDate = errors.month || errors.year;
        }

        if (this.props.nickname) {
            nickname = (
                <div className="row t100">
                    <TextInput
                        placeholder="Nickname"
                        altPlaceholder="Personal"
                        value={ this.model.label }
                        update={ this.update.bind(this, 'label') } />
                </div>
            );
        }

        return (
            <div className="credit-card">
                { nickname }
                <div className="row t100">
                    <TextInput format="card"
                        error={ errors.number }
                        value={ this.model.number }
                        update={ this.update.bind(this, 'number') } />
                </div>
                <div className="row t30-30-30">
                    <TextInput
                        format="expiration"
                        error={ errors.expirationDate }
                        value={ expirationDate }
                        update={ this.updateExpirationDate.bind(this) } />
                    <TextInput
                        format="cvv"
                        error={ errors.cvv }
                        value={ this.model.cvv }
                        update={ this.update.bind(this, 'cvv') } />
                    <PostalCode
                        error={ errors.zip }
                        value={ this.model.zip }
                        update={ this.update.bind(this, 'zip') } />
                </div>
            </div>
        );
    }
}

export default CreditCard;
