// @flow
import React from 'react';
import { expect } from 'chai';
import { mount } from 'enzyme';
import sinon from 'sinon';
import { spies } from '@test';

import C from './ParameterCreate.jsx';

describe('<ParameterCreate />', () => {
	let wrapper;
	const name = 'parameter';
	// shortcut for a func to update just the parameter obj, not the name
	const _updateParameter = (name, p, oldName) => {
		wrapper.setProps({
			param: p,
		});
	};
	const params = [];

	afterEach(() => {
		if(wrapper && wrapper.unmount)
			wrapper.unmount();
	});

	it(`saves the default value of a boolean parameter`, () => {
		let param = {
			type: '',
			default: '',
			description: '',
		};
		const updateParameter = sinon.spy(_updateParameter);

		wrapper = mount(
			<C
				name={name}
				param={param}
				params={params}
				updateParameter={updateParameter}
			/>
		);

		// sanity checks
		expect(wrapper.find('TypedField')).to.have.prop('name', name);

		wrapper.find('Input.custom-select').prop('onChange')( { target: { value: 'bool' }});
		wrapper.update();
		expect(wrapper.props().param).to.deep.equal(
			{
				type: 'bool',
				default: '',
				description: '',
			}
		);

		wrapper.find('input[type="radio"]').at(0).simulate('change', { target: { checked: 'true' }});;
		//wrapper.find('input[type="radio"]').at(0).simulate('change', { target: { value: 'true' }});;
		wrapper.update();
		expect(wrapper.props().param).to.deep.equal({
			type: 'bool',
			default: true,
			description: '',
		});
	});

	describe('regression', () => {
		it(`doesnt let min be larger than max in a range parameter`, () => {
			let param = {
				type: 'int8',
				default: '',
				description: '',
				range: [
					1,
					2
				]
			};
			const updateParameter = sinon.spy(_updateParameter);

			wrapper = mount(
				<C
					name={name}
					param={param}
					params={params}
					updateParameter={updateParameter}
				/>
			);

			// sanity checks
			expect(wrapper.find('TypedField')).to.have.prop('name', name);

			wrapper.find('Input[step="1"]').at(0).prop('onChange')( { target: { value: 3 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(0);
			expect(wrapper.props().param.range).to.deep.equal([1, 2]);

			wrapper.find('Input[step="1"]').at(0).prop('onChange')( { target: { value: 2 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(1);
			expect(wrapper.props().param.range).to.deep.equal([2, 2]);
		});
		it(`doesnt let min be larger than max in a range parameter for negative numbers`, () => {
			let param = {
				type: 'int8',
				default: '',
				description: '',
				range: [
					-1,
					-2
				]
			};
			const updateParameter = sinon.spy(_updateParameter);

			wrapper = mount(
				<C
					name={name}
					param={param}
					params={params}
					updateParameter={updateParameter}
				/>
			);

			// sanity checks
			expect(wrapper.find('TypedField')).to.have.prop('name', name);

			wrapper.find('Input[step="1"]').at(0).prop('onChange')( { target: { value: -1 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(0);
			expect(wrapper.props().param.range).to.deep.equal([-1, -2]);

			wrapper.find('Input[step="1"]').at(0).prop('onChange')( { target: { value: -2 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(1);
			expect(wrapper.props().param.range).to.deep.equal([-2, -2]);

			wrapper.find('Input[step="1"]').at(0).prop('onChange')( { target: { value: -3 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(2);
			expect(wrapper.props().param.range).to.deep.equal([-3, -2]);
		});
		it(`doesnt let max be smaller than min in a range parameter`, () => {
			let param = {
				type: 'int8',
				default: '',
				description: '',
				range: [
					3,
					4
				]
			};
			const updateParameter = sinon.spy(_updateParameter);

			wrapper = mount(
				<C
					name={name}
					param={param}
					params={params}
					updateParameter={updateParameter}
				/>
			);

			// sanity checks
			expect(wrapper.find('TypedField')).to.have.prop('name', name);

			wrapper.find('Input[step="1"]').at(1).prop('onChange')( { target: { value: 1 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(0);
			expect(wrapper.props().param.range).to.deep.equal([3, 4]);

			wrapper.find('Input[step="1"]').at(1).prop('onChange')( { target: { value: 3 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(1);
			expect(wrapper.props().param.range).to.deep.equal([3, 3]);
		});
		it(`doesnt let max be smaller than min in a range parameter for negative numbers`, () => {
			let param = {
				type: 'int8',
				default: '',
				description: '',
				range: [
					-3,
					-2
				]
			};
			const updateParameter = sinon.spy(_updateParameter);

			wrapper = mount(
				<C
					name={name}
					param={param}
					params={params}
					updateParameter={updateParameter}
				/>
			);

			// sanity checks
			expect(wrapper.find('TypedField')).to.have.prop('name', name);

			wrapper.find('Input[step="1"]').at(1).prop('onChange')( { target: { value: -5 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(0);
			expect(wrapper.props().param.range).to.deep.equal([-3, -2]);

			wrapper.find('Input[step="1"]').at(1).prop('onChange')( { target: { value: -3 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(1);
			expect(wrapper.props().param.range).to.deep.equal([-3, -3]);

			wrapper.find('Input[step="1"]').at(1).prop('onChange')( { target: { value: -1 }});
			wrapper.update();
			expect(updateParameter.callCount).to.equal(2);
			expect(wrapper.props().param.range).to.deep.equal([-3, -1]);
		});
	});
});
