import { mount, shallow } from 'enzyme';
import React from 'react';
import { SequencedDropdownsView } from 'web-foundation';

describe('<SequencedDropdownsView />', function() {
    const one = [
        { value: '1', title: 'option 1' },
        { value: '2', title: 'option 2' }
    ];

    const two = [
        { value: '1', title: 'option 1' },
        { value: '2', title: 'option 2' },
        { value: '3', title: 'option 3' }
    ];

    const three = [
        { value: '1', title: 'option 1' },
        { value: '2', title: 'option 2' }
    ];

    const settings = [
        { placeholder: 'Category 1', items: one },
        { placeholder: 'Category 2', items: two },
        { placeholder: 'Category 3', items: three }
    ];

    it('should initialize nicely', function() {
        const shallowed = shallow(
            <SequencedDropdownsView
                settings={ settings } />
            ),
            mounted = mount(
                <SequencedDropdownsView
                    settings={ settings } />
            );

        expect(shallowed.hasClass('sequenced-dropdowns')).to.be.true;

        expect(mounted.find('.dropdown')).to.have.length(settings.length);

        // all dropdowns except first should be disabled
        mounted.find('.dropdown').forEach(function(node, idx) {
            if (idx) {
                expect(node.hasClass('disabled')).to.be.true;
            }
        });
    });

    it('should all be disabled if I say so', function() {
        const wrapper = mount(
            <SequencedDropdownsView settings={ settings }
                disabled />
        );

        wrapper.find('.dropdown').forEach(function(node) {
            expect(node.hasClass('disabled')).to.be.true;
        });
    });

    it('should disable on command', function() {
        const wrapper = mount(
            <SequencedDropdownsView settings={ settings } />
        );

        expect(wrapper.prop('disabled')).to.be.false;

        wrapper.setProps({
            disabled: true
        });

        expect(wrapper.prop('disabled')).to.be.true;
    });

    it('should stay disabled for other props', function() {
        const wrapper = mount(
            <SequencedDropdownsView
                disabled
                settings={ settings } />
        );

        expect(wrapper.prop('disabled')).to.be.true;

        wrapper.setProps({
            random: true
        });

        expect(wrapper.prop('disabled')).to.be.true;
    });

    it('should re-enable on command as well', function() {
        const wrapper = mount(
            <SequencedDropdownsView
                disabled
                settings={ settings } />
        );

        expect(wrapper.prop('disabled')).to.be.true;

        wrapper.setProps({
            disabled: false
        });

        expect(wrapper.prop('disabled')).to.be.false;
    });

    it('should call onSelect intended for one of the dropdowns', function() {
        const _settings = settings.slice(),
            spy = sinon.spy(),
            target = 1;

        _settings[0] = Object.assign({}, _settings[0]);
        _settings[0].onSelect = spy;

        const wrapper = mount(
            <SequencedDropdownsView settings={ _settings } />
        );

        wrapper.find('.dropdown').find('.option').at(target).simulate('click');

        expect(spy.callCount).to.equal(1);
        expect(spy.getCall(0).args[0].title)
            .to.equal(_settings[0].items[target].title);
    });

    it('should enable the next dropdown after a selection', function() {
        const wrapper = mount(
            <SequencedDropdownsView
                settings={ settings } />
            ),
            dropdownIdx = 1,
            optionIdx = settings[0].items.length - 1; // last option

        expect(wrapper.find('.dropdown').at(dropdownIdx).hasClass('disabled'))
            .to.be.true;

        wrapper.find('.dropdown').find('.option')
            .at(optionIdx).simulate('click');

        expect(wrapper.find('.dropdown').at(dropdownIdx).hasClass('disabled'))
            .to.be.false;
    });

    it('should override options through onSelect', function() {
        // selection for dropdown 0 -> options for dropdown 1
        // 'option 1' -> ['x1', 'y1']
        // 'option 2' -> ['x2', 'y2']
        function onSelect(idx, option) {
            let i, value;

            for (i = 0; i < settings[idx].items.length; i++) {
                value = settings[idx].items[i].value;
                if (option.value === value) {
                    return [
                        { title: `x${value}`, value: `x${value}` },
                        { title: `y${value}`, value: `y${value}` }
                    ];
                }
            }
        }

        function check(value, node, idx) {
            const title = idx === 0 ? `x${value}` : `y${value}`;

            expect(node.text()).to.equal(title);
        }

        const wrapper = mount(
            <SequencedDropdownsView
                onSelect={ onSelect }
                settings={ settings } />
        );
        let i;

        for (i = 0; i < settings[0].items.length; i++) {
            wrapper.find('.dropdown').find('.option')
                .at(i).simulate('click');

            wrapper.find('.dropdown').at(1).find('.option')
                .forEach(check.bind(this, settings[0].items[i].value));
        }
    });

    it('should not override options if no array returned', function() {
        function onSelect() {
            return null;
        }

        function check(node, idx) {
            const title = settings[1].items[idx].title;

            expect(node.text()).to.equal(title);
        }

        const wrapper = mount(
            <SequencedDropdownsView
                onSelect={ onSelect }
                settings={ settings } />
        );
        let i;

        for (i = 0; i < settings[0].items.length; i++) {
            wrapper.find('.dropdown').find('.option')
                .at(i).simulate('click');

            wrapper.find('.dropdown').at(1).find('.option')
                .forEach(check.bind(this));
        }
    });

    it('should call onComplete when all dropdowns are selected', function() {
        const spy = sinon.spy(),
            wrapper = mount(
                <SequencedDropdownsView
                    onComplete={ spy }
                    settings={ settings } />
            );

        wrapper.find('.dropdown').forEach((node, idx) => {
            node.find('.option').at(settings[idx].items.length - 1)
                .simulate('click');
        });

        wrapper.find('.dropdown').forEach((node) => {
            expect(node.hasClass('disabled')).to.be.false;
        });

        expect(spy.callCount).to.equal(1);
        expect(spy.getCall(0).args[0]).to.have.length(settings.length);
    });

    it('should enable subsequent dropdowns if values provided', function() {
        const _settings = settings;

        _settings[0].value = one[0].value;

        const wrapper = mount(
            <SequencedDropdownsView settings={ _settings } />
        );

        expect(wrapper.find('.dropdown').at(1).hasClass('disabled'))
            .to.be.false;

        expect(wrapper.find('.dropdown').at(2).hasClass('disabled'))
            .to.be.true;
    });
});
