import { mount } from 'enzyme';
import React from 'react';
import ReactDOM from 'react-dom';
import { Address } from 'web-foundation';

import {
    BestCase as GoogleGeocode,
    OtherCase as GoogleGeocodeOther,
    AnotherCase as GoogleGeocodeMore
} from '../data/google-geocode';

describe('Address', function() {
    it('should transform field names from the api', function() {
        /* eslint-disable camelcase */
        const model = new Address.Model({
                street_address_1: 'beansbeansbeans',
                street_address_2: 'yoloyoloyolo',
                zip_code: '12345'
            }),
            out = model.out();
        /* eslint-enable camelcase */

        expect(model.street).to.equal('beansbeansbeans');
        expect(model.apt).to.equal('yoloyoloyolo');
        expect(model.zip).to.equal('12345');

        expect(model.street_address_1).to.be.undefined;
        expect(model.street_address_2).to.be.undefined;
        expect(model.zip_code).to.be.undefined;

        expect(out.street).to.be.undefined;
        expect(out.apt).to.be.undefined;
        expect(out.zip).to.be.undefined;

        expect(out.street_address_1).to.equal('beansbeansbeans');
        expect(out.street_address_2).to.equal('yoloyoloyolo');
        expect(out.zip_code).to.equal('12345');
    });

    it('should format the address in a single line', function() {
        const model = new Address.Model();

        expect(model.singleLine()).to.equal('');

        model.fill({
            street: 'one',
            city: 'two',
            state: 'CA',
            zip: 'three'
        });

        expect(model.singleLine()).to.equal('one, two, CA three');

        model.apt = 'beans';

        expect(model.singleLine()).to.equal('one, beans, two, CA three');
    });

    it('should parse a google place', function() {
        const model = Address.Model.fromGooglePlace(GoogleGeocode),
            omodel = Address.Model.fromGooglePlace(GoogleGeocodeOther),
            mmodel = Address.Model.fromGooglePlace(GoogleGeocodeMore),
            bmodel = Address.Model.fromGooglePlace({}),
            obmodel = Address.Model.fromGooglePlace();

        expect(model.city).to.equal('San Francisco');
        expect(model.state).to.equal('CA');
        expect(model.country).to.equal('US');
        expect(model.street).to.equal('475 Valencia St');
        expect(model.zip).to.equal('94103');
        expect(model.lat).to.equal(37.7653549);
        expect(model.lng).to.equal(-122.42174339999997);

        expect(omodel.city).to.equal('SF');
        expect(omodel.state).to.equal('CA');
        expect(omodel.country).to.equal('US');
        expect(omodel.street).to.equal('475 Valencia Street');
        expect(omodel.zip).to.equal('94103');
        expect(omodel.lat).to.equal(37.7653549);
        expect(omodel.lng).to.equal(-122.42174339999997);

        expect(mmodel.street).to.equal('Valencia Street');
        expect(bmodel).to.be.undefined;
        expect(obmodel).to.be.undefined;
    });
});

describe('<Address />', function() {
    it('should initialize all nice like', function() {
        const wrapper = mount(<Address.View />);

        expect(wrapper.children().find('.row')).to.have.length(2);
        expect(wrapper.find('label')).to.have.length(1);
        expect(
            wrapper.find('.row.t75-25')
                .find('label')
                .text()
        ).to.equal('Address');
        expect(
            wrapper.find('.row.t75-25')
                .find('input')
        ).to.have.length(2);
        expect(
            wrapper.find('.row.t75-25')
                .find('input')
                .at(0)
                .prop('placeholder')
        ).to.equal('Street Address');
        expect(
            wrapper.find('.row.t75-25')
                .find('input')
                .at(1)
                .prop('placeholder')
        ).to.equal('Apt / Suite');
        expect(
            wrapper.find('.row.t25-50-25')
                .find('input')
        ).to.have.length(2);
        expect(
            wrapper.find('.row.t25-50-25')
                .find('div.dropdown')
        ).to.have.length(1);
    });

    it('should have all the states', function() {
        const wrapper = mount(<Address.View lock={ false } />);

        expect(wrapper.find('.option'))
            .to.have.length(Address.Model.statesOptions.length);
    });

    it('should not have label if passed null', function() {
        const wrapper = mount(<Address.View label={ null } />);

        expect(wrapper.find('label')).to.have.length(0);
    });

    it('should allow abbreviated states', function() {
        const wrapper = mount(
            <Address.View
                lock={ false }
                abbreviated />);

        expect(wrapper.find('.option'))
            .to.have.length(Address.Model.statesOptions.length);

        wrapper.find('.option').every((node) => {
            expect(node.text()).to.have.lengthOf(2);
        });
    });

    it('should pass selected state option value to model', function() {
        const model = new Address.Model(),
            wrapper = mount(
                <Address.View
                    abbreviated
                    lock={ false }
                    model={ model }/>);

        wrapper.find('.header').simulate('click');

        expect(wrapper.find('.option'))
            .to.have.length(Address.Model.statesOptionsAbbrev.length);

        wrapper.find('.option').first().simulate('click');

        expect(model.state)
            .to.equal(Address.Model.statesOptionsAbbrev[0].value);
    });

    it('should disable city/state if empty and zip not completed', function() {
        const wrapper = mount(<Address.View />);

        expect(wrapper.find('.text-input').at(3).hasClass('disabled'))
            .to.be.true;
        expect(wrapper.find('.dropdown').first().hasClass('disabled'))
            .to.be.true;
    });

    it('should enable city/state if address from zip returned', function() {
        const model = new Address.Model(),
            wrapper = mount(<Address.View model={ model } />);

        wrapper.instance().fill({
            city: 'San Francisco',
            state: 'CA'
        });

        wrapper.instance().forceUpdate();

        expect(wrapper.find('.text-input').at(3).hasClass('disabled'))
            .to.be.false;
        expect(wrapper.find('.dropdown').first().hasClass('disabled'))
            .to.be.false;
    });

    it('should add a row for notes', function() {
        const wrapper = mount(<Address.View withNotes />);

        expect(wrapper.children().find('.row')).to.have.length(3);
        expect(
            wrapper.find('.row.t100')
                .find('textarea')
        ).to.have.length(1);
        expect(
            wrapper.find('.row.t100')
                .find('textarea')
                .prop('placeholder')
        ).to.equal('Notes for the Postmate');
    });

    it('should fill with stuff', function() {
        const model = new Address.Model(),
            wrapper = mount(<Address.View model={ model } />),
            node = ReactDOM.findDOMNode(wrapper.instance());

        model.fill({
            street: 'one',
            apt: 'two',
            zip: '123',
            city: 'four',
            state: 'CA'
        });

        wrapper.instance().forceUpdate();

        expect(node.getElementsByTagName('input')[0].value).to.equal('one');
        expect(node.getElementsByTagName('input')[1].value).to.equal('two');
        expect(node.getElementsByTagName('input')[2].value).to.equal('123');
        expect(node.getElementsByTagName('input')[3].value).to.equal('four');
    });

    it('should fill on geocoder events', function() {
        const wrapper = mount(<Address.View />),
            node = ReactDOM.findDOMNode(wrapper.instance());

        wrapper.instance().fill({
            street: 'one',
            apt: 'two',
            zip: '123'
        });
        wrapper.instance().forceUpdate();

        expect(node.getElementsByTagName('input')[0].value).to.equal('one');
        expect(node.getElementsByTagName('input')[1].value).to.equal('two');
        expect(node.getElementsByTagName('input')[2].value).to.equal('123');

        wrapper.instance().fill({
            street: 'one1',
            apt: 'two1',
            zip: '1231'
        });
        wrapper.instance().forceUpdate();

        expect(node.getElementsByTagName('input')[0].value).to.equal('one1');
        expect(node.getElementsByTagName('input')[1].value).to.equal('two1');
        expect(node.getElementsByTagName('input')[2].value).to.equal('1231');
    });

    it('should accept different field errors', function(done) {
        const wrapper = mount(<Address.View />);

        wrapper.instance().setErrorMessages({
            street: 'xyz-01234'
        });
        wrapper.instance().formValidate(() => {
            expect(wrapper.find('.text-input')
                .find('.error-tooltip').first().text()).to.equal('xyz-01234');
            done();
        });
    });
});
