"use strict";

const Promise = require("bluebird");
const React = require("react");
const ReactDOM = require("react-dom");
const documentReadyPromise = require("document-ready-promise");
const axios = require("axios");

// The below require path is a placeholder, filled out at build time, using aliasify (see the budo-express config)
const DisplayComponent = require("__internal_display_component");

const Error = require("./error.jsx");
const Running = require("./running.jsx");

function Root() {
	let [ data, setData ] = React.useState(null);
	let [ error, setError ] = React.useState(null);
	let [ running, setRunning ] = React.useState(true);
	
	function processData(incomingData) {
		if (incomingData.type === "error") {
			setRunning(false);
			setError(incomingData.payload);
		} else if (incomingData.type === "output") {
			setRunning(false);
			setError(null);
			setData(incomingData.payload);
		} else if (incomingData.type === "running") {
			setRunning(true);
		}
	}

	React.useEffect(() => {
		let eventReceived = false;

		let eventStream = new EventSource("/stream");

		eventStream.addEventListener("message", (event) => {
			eventReceived = true;
			processData(JSON.parse(event.data));
		});
		
		Promise.try(() => {
			return axios.get("/initial_data");
		}).then((response) => {
			if (!eventReceived) {
				processData(response.data);
			}
		});

		return function cleanup() {
			eventStream.close();
		}
	}, []);

	if (data != null) {
		return (<>
			{(error != null)
				? <Error {... error} />
				: null
			}
			{(running === true)
				? <Running />
				: null
			}
			<DisplayComponent data={data} />
		</>);
	} else {
		if (error == null) {
			return "Loading initial data, please wait...";
		} else {
			return <Error {... error} />;
		}
	}
}

Promise.try(() => {
	return documentReadyPromise();
}).then(() => {
	ReactDOM.render(<Root />, document.getElementById("render"));
});
