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

import { PlotterEditor as C } from '.';
import {  getValidPlotterObj as getValidObj } from '@helpers/beat';

import testPlotters from '@test/test_plotters.json';
import testDfs from '@test/test_dfs.json';
import testLibs from '@test/test_libs.json';

const libs = [];

describe('<PlotterEditor />', () => {
	let wrapper;

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

	describe('accepts', () => {
		const plots = [
			{
				name: 'test/myplot/1',
				contents: {
					description: 'A basic plotter as a sanity test for the PlotterEditor',
					language: 'python',
					parameters: {
						'parameter_1': {
							type: 'string',
							default: 'default',
							description: 'description',
						}
					},
					dataformat: "plot/bar/1",
					uses: {
						'library': 'plot/baselib/1',
					}
				}
			}
		].concat(testPlotters.map(a => getValidObj(a)));

		plots.forEach(function(plot){
			const saveFunc = () => {};
			const updateFunc = () => {};
			const dfs = testDfs.filter(d => d.name.startsWith('plot')).map(testDfs => testDfs.name);
			it(`${ plot.name }`, () => {
				wrapper = mount(
					<C
						data={getValidObj(plot)}
						plotters={plots}
						dataformats={plot.contents.dataformat}
						plotDfNames={dfs}
						libraries={libs}
						saveFunc={saveFunc}
						updateFunc={updateFunc}
					/>
				);
				expect(wrapper).to.have.props(
					['data', 'plotters', 'dataformats', 'libraries', 'saveFunc', 'updateFunc']
				)
			});
		});
	});

	describe('creates', () => {
		it('test/createplot/1', () => {
			const saveFunc = sinon.spy();
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
			const plotName = 'test/createplot/1';
			const dfs = testDfs.filter(d => d.name.startsWith('plot')).map(testDfs => testDfs.name);
			wrapper = mount(
				<C
					data={getValidObj({name: plotName, contents: {}})}
					plotters={[]}
					dataformats={testDfs}
					plotDfNames={dfs}
					libraries={testLibs}
					saveFunc={saveFunc}
					updateFunc={updateFunc}
				/>
			);

			expect(wrapper).to.have.props(
				['data', 'plotters', 'dataformats', 'plotDfNames', 'libraries', 'saveFunc', 'updateFunc']
			);

			expect(wrapper.props().data).to.have.property('name', plotName);

			expect(wrapper.props().data.contents).to.have.property('dataformat', '');
			expect(wrapper.props().data.contents).to.have.property('dataformat').with.lengthOf(0);
			expect(wrapper.props().data.contents).to.have.property('language').with.lengthOf(6);
			expect(wrapper.props().data.contents).to.have.property('language', 'python');
			wrapper.find('#plDf select').simulate('change', { target: { value: 'user/anotherdataformat/1'}});
			expect(updateFunc.callCount).to.equal(1);

			expect(wrapper.props().data.contents).to.have.property('dataformat', 'user/anotherdataformat/1');
			expect(wrapper.props().data.contents).to.have.property('language', 'python');

			expect(wrapper.props().data.contents).to.have.property('description').with.lengthOf(0);
			expect(wrapper.props().data.contents).to.have.property('language').with.lengthOf(6);
			expect(wrapper.props().data.contents).to.have.property('dataformat').with.lengthOf(24);
			expect(wrapper.props().data.contents).to.have.property('parameters').that.deep.equals({});
			expect(wrapper.props().data.contents).to.have.property('uses').that.deep.equals({});
			expect(wrapper.props().data.contents).to.deep.equal({
				'description': '',
				'uses': {},
				'parameters': {},
				'language': 'python',
				'dataformat': 'user/anotherdataformat/1'
			});

		});

		it('test/plot_add_lib/1', () => {
			const saveFunc = sinon.spy();
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
			const plotName = 'test/plot_other/1';
			const dfs = testDfs.filter(d => d.name.startsWith('plot')).map(testDfs => testDfs.name);
			wrapper = mount(
				<C
					data={getValidObj({name: plotName, contents: {}})}
					plotters={[]}
					dataformats={testDfs}
					plotDfNames={dfs}
					libraries={testLibs}
					saveFunc={saveFunc}
					updateFunc={updateFunc}
				/>
			);

			expect(wrapper).to.have.props(
				['data', 'plotters', 'dataformats', 'plotDfNames', 'libraries', 'saveFunc', 'updateFunc']
			);

			expect(wrapper.props().data).to.have.property('name', plotName);

			expect(wrapper.props().data.contents).to.have.property('dataformat', '');
			expect(wrapper.props().data.contents).to.have.property('dataformat').with.lengthOf(0);
			expect(wrapper.props().data.contents).to.have.property('language').with.lengthOf(6);
			expect(wrapper.props().data.contents).to.have.property('language', 'python');
			expect(wrapper.props().data.contents).to.have.property('parameters').that.deep.equals({});
			expect(wrapper.props().data.contents).to.have.property('uses').that.deep.equals({});

			wrapper.find('button#newLibraryBtn').simulate('click');
			wrapper.find('#usedLibs CacheInput[type="text"]').prop('onChange')({ target: { value: 'lib'}});
			expect(updateFunc.callCount).to.equal(2);

			wrapper.find('#usedLibs select').simulate('change', { target: { value: 'user/anotherlib/1'}});
			expect(updateFunc.callCount).to.equal(3);

			expect(wrapper.props().data.contents).to.deep.equal({
				'description': '',
				'uses': {
					lib: 'user/anotherlib/1'
				},
				'language': 'python',
				'parameters': {},
				'dataformat': ''
			});
		});

		it('test/plot_add_param/1', () => {
			const saveFunc = sinon.spy();
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
			const plotName = 'test/plot_param/1';
			const dfs = testDfs.filter(d => d.name.startsWith('plot')).map(testDfs => testDfs.name);
			wrapper = mount(
				<C
					data={getValidObj({name: plotName, contents: {}})}
					plotters={[]}
					dataformats={testDfs}
					plotDfNames={dfs}
					libraries={testLibs}
					saveFunc={saveFunc}
					updateFunc={updateFunc}
				/>
			);

			expect(wrapper).to.have.props(
				['data', 'plotters', 'dataformats', 'plotDfNames', 'libraries', 'saveFunc', 'updateFunc']
			);

			expect(wrapper.props().data).to.have.property('name', plotName);

			expect(wrapper.props().data.contents).to.have.property('dataformat', '');
			expect(wrapper.props().data.contents).to.have.property('dataformat').with.lengthOf(0);
			expect(wrapper.props().data.contents).to.have.property('language').with.lengthOf(6);
			expect(wrapper.props().data.contents).to.have.property('language', 'python');
			expect(wrapper.props().data.contents).to.have.property('parameters').that.deep.equals({});
			expect(wrapper.props().data.contents).to.have.property('uses').that.deep.equals({});
			wrapper.find('button#newParameterBtn').simulate('click');
			expect(updateFunc.callCount).to.equal(1);

			wrapper.find('CacheInput[placeholder="Parameter name..."]').prop('onChange')( { target: { value: 'offset' }});
			expect(updateFunc.callCount).to.equal(2);
			wrapper.find('#paramsForm select').prop('onChange')( { target: { value: 'int32' }});
			expect(updateFunc.callCount).to.equal(3);
			wrapper.find('input[placeholder="Default"]').simulate('change', { target: { value: '1' }});
			expect(updateFunc.callCount).to.equal(4);

			expect(wrapper.props().data.contents.parameters).to.have.deep.property('offset', {
				'default': '1',
				'type': 'int32',
				'description': '',
			});

			expect(wrapper.props().data.contents).to.deep.equal({
				'description': '',
				'uses': {},
				'language': 'python',
				'parameters': {
					'offset': {
						'default': '1',
						'type': 'int32',
						description: '',
					}
				},
				'dataformat': ''
			});
		});
	});
});
