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

beforeEach(cleanup);

describe('Token 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(<TokenSuggest
            initialSuggestOptions={animals}
            inputValue={''}
            onValueChange={() => { }}
        />);

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

    test('02 - List of options with a value, without tokenOpener will not show the dropdown', () => {
        const wrapper = shallow(<TokenSuggest
            initialSuggestOptions={animals}
            inputValue={'Lio'}
            onValueChange={() => { }}
        />);

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

    test('03 - Typing the opener token will display the dropdown', () => {
        const onValueChange = jest.fn();
        const wrapper = shallow(<TokenSuggest
            initialSuggestOptions={animals}
            inputValue={'My animal is '}
            onValueChange={onValueChange}
        />);

        const newValue = 'My animal is <';
        wrapper.find(InputDropDownDrawer).prop('onValueChange')({ target: { value: newValue } });

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().showDropDown).toEqual(true);
        expect(wrapper.state().suggestOptions).toEqual(animals);
        expect(wrapper.state().currentToken).toEqual('');
        expect(onValueChange).toHaveBeenCalledWith(newValue, false);
    });

    test('04 - Typing after the opener token was typed will display the dropdown', () => {
        const onValueChange = jest.fn();
        const wrapper = shallow(<TokenSuggest
            initialSuggestOptions={animals}
            inputValue={'My animal is <L'}
            onValueChange={onValueChange}
        />);

        const newValue = 'My animal is <Li';
        wrapper.find(InputDropDownDrawer).prop('onValueChange')({ target: { value: newValue } });

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().showDropDown).toEqual(true);
        expect(wrapper.state().suggestOptions).toEqual([animals[5]]);
        expect(wrapper.state().currentToken).toEqual('Li');
        expect(onValueChange).toHaveBeenCalledWith(newValue, false);
    });

    test('05 - Typing the closer will hide the dropdown', () => {
        const onValueChange = jest.fn();
        const wrapper = shallow(<TokenSuggest
            initialSuggestOptions={animals}
            inputValue={'My animal is <Lion'}
            onValueChange={onValueChange}
        />);

        const newValue = 'My animal is <Lion>';
        wrapper.find(InputDropDownDrawer).prop('onValueChange')({ target: { value: newValue } });

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().showDropDown).toEqual(false);
        expect(wrapper.state().suggestOptions).toEqual([]);
        expect(wrapper.state().currentToken).toEqual('');
        expect(onValueChange).toHaveBeenCalledWith(newValue, true);
    });

    test('06 - Select a token after having typed the opener will complete the input and hide the dropdown', () => {
        const onValueChange = jest.fn();
        const wrapper = shallow(<TokenSuggest
            initialSuggestOptions={animals}
            inputValue={'My animal is <D'}
            onValueChange={onValueChange}
        />);

        wrapper.find(InputDropDownDrawer).prop('onSelectOption')('Dog');

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().showDropDown).toEqual(false);
        expect(wrapper.state().suggestOptions).toEqual([]);
        expect(wrapper.state().currentToken).toEqual('');
        expect(onValueChange).toHaveBeenCalledWith('My animal is <Dog> ', true);
    });

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

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

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

    test('08 - Different opener and closer tokens and after token message are accepted', () => {
        const onValueChange = jest.fn();
        const wrapper = shallow(<TokenSuggest
            defaultAfterToken={' and it is cool!'}
            initialSuggestOptions={animals}
            inputValue={'My animal is [S'}
            onValueChange={onValueChange}
            tokenCloser={']'}
            tokenOpener={'['}
        />);

        wrapper.find(InputDropDownDrawer).prop('onSelectOption')('Shark');

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().showDropDown).toEqual(false);
        expect(wrapper.state().suggestOptions).toEqual([]);
        expect(wrapper.state().currentToken).toEqual('');
        expect(onValueChange).toHaveBeenCalledWith('My animal is [Shark] and it is cool!', true);
    });

    test('09 - Test to control props passed to child component', () => {
        const customEmptyStateMessage = <div>Custom test message</div>;
        const emptyStateMessage = 'Empty test message';
        const inputValue = 'Animal';
        const onEnterKeyPressed = jest.fn();
        const onValueChange = jest.fn();
        const placeholder = 'Select animal';
        const readOnly = false;
        const showDropDownOnEmpty = true;
        const wrapper = shallow(<TokenSuggest
            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('');
        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([]);
    });

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

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

    });
});
