// @flow
import * as React from 'react';
import {
	Button,
	Modal,
	ModalBody,
	ModalHeader,
	ModalFooter,
} from 'reactstrap';
import {
	generateDatabaseTemplate,
	generateAlgorithmTemplate,
	generateLibraryTemplate,
	generatePlotterTemplate,
} from '@helpers/api';
import { copyObj } from '@helpers';
import type { BeatEntity, BeatObject } from '@helpers/beat';
import { pluralize } from '@helpers/beat';

type Props = {
	data: BeatObject,
	entity: BeatEntity,
};

type State = {
	infoOpen: boolean,
	confirmOpen: boolean,
};

export default class EntityTemplateGenerationButton extends React.Component<Props, State> {
	constructor(props: Props){
		super(props);
	}

	state = {
		infoOpen: false,
		confirmOpen: false,
	}

	toggleInfo = (val: boolean = !this.state.infoOpen) => {
		this.setState({ infoOpen: val });
	}

	toggleConfirm = (val: boolean = !this.state.confirmOpen) => {
		this.setState({ confirmOpen: val });
	}

	click = async (confirm: boolean) => {
		let uses;
		let res;
		switch(this.props.entity){
			case('database'):
				if(!this.props.data.contents.protocols)
					throw new Error(`Bad database object, no protocols field: ${ this.props.data.contents }`);
				// need to find all the views
				let views = Array.from(new Set(
					this.props.data.contents.protocols
					.map(p => p.sets.map(s => s.view))
					.reduce((a, vs) => [...a, ...vs], [])
				));
				res = await generateDatabaseTemplate(this.props.data.name, confirm, views);
				break;
			case('algorithm'):
				// find if the alg has parameters
				// find the used libraries
				if(!this.props.data.contents.parameters)
					throw new Error(`Bad alg object, no params field: ${ this.props.data.contents }`);
				res = await generateAlgorithmTemplate(this.props.data.name, confirm, this.props.data.contents);
				break;
			case('library'):
				// find the used libraries
				uses = copyObj(this.props.data.contents.uses);
				res = await generateLibraryTemplate(this.props.data.name, confirm, uses);
				break;
			case('plotter'):
				// find the used libraries and parameters
				uses = copyObj(this.props.data.contents.parameters);
				res = await generatePlotterTemplate(this.props.data.name, confirm, this.props.data.contents);
				break;
			default:
				throw new Error(`Cannot generate template for entity "${ this.props.entity }"`);
		}

		// inspect the result
		if(res === false){
			// the python file already existed, ask for confirmation to overwrite
			this.toggleConfirm(true);
		} else {
			// its fine
			this.toggleInfo(true);
		}
	}

	render = () => {
		return (
			<React.Fragment>
				<Button outline
					color='danger'
					className='mx-auto'
					onClick={e => this.click(false)}
					title={`Some types of objects (databases, algorithms, and libraries) need Python files to be used in experiments. You may generate a template Python file to provide a starting point for development.`}
				>
					Generate Python File
				</Button>
				<br />
				<Modal color='info' isOpen={this.state.infoOpen} toggle={e => this.toggleInfo(false)}>
					<ModalHeader toggle={e => this.toggleInfo(false)}>
						Information about the template file
					</ModalHeader>
					<ModalBody>
						<p>
							You have generated a template Python file to provide a starting point for development for this object.
						</p>
						The template { this.props.entity } Python file for this object can be found in the path:
						<pre className='preInline'>
							/your/beat/prefix/{ pluralize(this.props.entity) }/{ this.props.data.name }.py
						</pre>
					</ModalBody>
				</Modal>
				<Modal color='info' isOpen={this.state.confirmOpen} toggle={e => this.toggleConfirm(false)}>
					<ModalHeader toggle={e => this.toggleConfirm(false)}>
						Confirm Overwrite
					</ModalHeader>
					<ModalBody>
						The generated Python file will overwrite the Python file that already exists at:
						<pre className='preInline'>
							/your/beat/prefix/{ pluralize(this.props.entity) }/{ this.props.data.name }.py
						</pre>
						Are you sure you want to overwrite this file?
					</ModalBody>
					<ModalFooter>
						<Button color="primary" onClick={e => { this.toggleConfirm(false); this.click(true); }}>Overwrite</Button>{' '}
						<Button color="secondary" onClick={e => this.toggleConfirm(false)}>Cancel</Button>
					</ModalFooter>
				</Modal>
			</React.Fragment>
		);
	}
};
