import * as React from 'react';
import { shallow } from 'enzyme';
import { cleanup } from 'react-testing-library';
import 'jest-styled-components';
import InputSuggest from '../../../components/InputSuggest';
import AnimatedLabel from '../../../components/AnimatedLabel';
import { InputDropDownDrawer } from '../../../components/InputDropDownDrawer';

beforeEach(cleanup);

describe('Input Suggest', () => {
    const animals = [
        { id: 1, toString: () => 'Bear' },
        { id: 2, toString: () => 'Bee' },
        { id: 3, toString: () => 'Cat' },
        { id: 4, toString: () => 'Dog' },
        { id: 5, toString: () => 'Elefant' },
        { id: 6, toString: () => 'Lion' },
        { id: 7, toString: () => 'Sea Lion' },
        { id: 8, toString: () => 'Shark' }
    ];

    test('01 - List of options with empty input does not show the dropdown', () => {
        const wrapper = shallow(<InputSuggest
            initialSuggestOptions={animals}
            inputValue={''}
            onValueChange={() => { }}
        />);

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().showDropDown).toEqual(false);
    });

    test('02 - List of options with a value that matches some of them will store a filtered list in the state', () => {
        const wrapper = shallow(<InputSuggest
            initialSuggestOptions={animals}
            inputValue={'Lio'}
            onValueChange={() => { }}
        />);

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().suggestOptions).toEqual([animals[5], animals[6]]);
    });

    test('03 - List of options with a value that matches some of them, according to a custom function, will store a filtered list in the state', () => {
        const numberEqualsLength = (option: { toString: () => string }, currentValue: string) => (
            parseInt(currentValue) === option.toString().length
        );
        const wrapper = shallow(<InputSuggest
            initialSuggestOptions={animals}
            inputValue={'3'}
            onValueChange={() => { }}
            optionMatches={numberEqualsLength}
        />);

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().suggestOptions).toEqual([animals[1], animals[2], animals[3]]);
    });

    test('04 - Handle onValueChange will update the state options', () => {
        const onValueChange = jest.fn();
        const wrapper = shallow(<InputSuggest
            initialSuggestOptions={animals}
            inputValue={'S'}
            onValueChange={onValueChange}
        />);

        const newValue = 'Sh';
        wrapper.find(InputDropDownDrawer).prop('onValueChange')({ target: { value: newValue } });

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().showDropDown).toEqual(true);
        expect(wrapper.state().suggestOptions).toEqual([animals[7]]);
        expect(onValueChange).toHaveBeenCalledWith(newValue);
    });

    test('05 - Handle onDropDownEvent will update the showDropDown attribute in the state', () => {
        const onValueChange = jest.fn();
        const wrapper = shallow(<InputSuggest
            initialSuggestOptions={animals}
            inputValue={'S'}
            onValueChange={onValueChange}
        />);

        wrapper.find(InputDropDownDrawer).prop('onDropDownEvent')({}, false);

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().showDropDown).toEqual(false);
        expect(onValueChange).not.toHaveBeenCalled();
    });

    test('06 - Handle onSelectOption will update the state options to a list of only that option and showDropDown on false', () => {
        const onValueChange = jest.fn();
        const wrapper = shallow(<InputSuggest
            initialSuggestOptions={animals}
            inputValue={'Be'}
            onValueChange={onValueChange}
        />);

        const option = 'Bear';
        wrapper.find(InputDropDownDrawer).prop('onSelectOption')(option);

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().showDropDown).toEqual(false);
        expect(wrapper.state().suggestOptions).toEqual([animals[0]]);
        expect(onValueChange).toHaveBeenCalledWith(option);
    });

    test('07 - Test to control props passed to child component', () => {
        const customEmptyStateMessage = <div>Custom test message</div>;
        const emptyStateMessage = 'Empty test message';
        const inputValue = 'Ca';
        const onEnterKeyPressed = jest.fn();
        const onValueChange = jest.fn();
        const placeholder = 'Select animal';
        const readOnly = false;
        const showDropDownOnEmpty = true;
        const wrapper = shallow(<InputSuggest
            customEmptyStateMessage={customEmptyStateMessage}
            emptyStateMessage={emptyStateMessage}
            initialSuggestOptions={animals}
            inputValue={inputValue}
            onEnterKeyPressed={onEnterKeyPressed}
            onValueChange={onValueChange}
            placeholder={placeholder}
            readOnly={readOnly}
            showDropDownOnEmpty={showDropDownOnEmpty}
        />);

        expect(wrapper).toMatchSnapshot();

        const inputDropDownDrawerProps = wrapper.find(InputDropDownDrawer).props();
        expect(inputDropDownDrawerProps.customEmptyStateMessage).toBe(customEmptyStateMessage);
        expect(inputDropDownDrawerProps.emptyStateMessage).toBe(emptyStateMessage);
        expect(inputDropDownDrawerProps.highlightedChunk).toBe(inputValue);
        expect(inputDropDownDrawerProps.inputValue).toBe(inputValue);
        expect(inputDropDownDrawerProps.onEnterKeyPressed).toBe(onEnterKeyPressed);
        expect(inputDropDownDrawerProps.placeholder).toBe(placeholder);
        expect(inputDropDownDrawerProps.readOnly).toBe(readOnly);
        expect(inputDropDownDrawerProps.showDropDown).toEqual(false);
        expect(inputDropDownDrawerProps.suggestOptions).toEqual([animals[2]]);
    });

    test('08 - Adding custom Input', () => {
        const onValueChange = jest.fn();
        const placeholdertext = "Headline"
        const wrapper = shallow(<InputSuggest
            customInput={AnimatedLabel}
            customInputProps={
                {
                    placeholder: placeholdertext,
                    value: this.state.value,
                    onValueChange: this.onValueChange
                }
            }
            initialSuggestOptions={animals}
            inputValue={'Be'}
            onValueChange={onValueChange}
        />);

        wrapper.find(AnimatedLabel).prop('placeholder');
        const AnimatedLabelProps = wrapper.find(AnimatedLabel).props();
        expect(AnimatedLabelProps.placeholder).toBe(placeholdertext);

    });
});
