import { Meteor } from 'meteor/meteor';
import React, { useState } from 'react';
import { useTracker } from 'meteor/react-meteor-data';
import _ from 'lodash';
import SimpleTable from "/imports/ui/util/SimpleTable";
import TextField from "@mui/material/TextField";
import Button from "@mui/material/Button";
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import {Students} from "/imports/api/students";
import {Sites} from "/imports/api/sites";
import Box from "@mui/material/Box";
import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
import ToggleButton from "@mui/material/ToggleButton";
import {InputLabel, List, ListItemButton, ListItemText, Switch} from "@mui/material";
import FormControl from "@mui/material/FormControl";
import Dialog from "@mui/material/Dialog";
import DialogTitle from "@mui/material/DialogTitle";
import DialogContent from "@mui/material/DialogContent";
import DialogActions from "@mui/material/DialogActions";
import FormControlLabel from "@mui/material/FormControlLabel";
import Checkbox from "@mui/material/Checkbox";

const cssSitesSelect = {
	margin: '0.6rem 0',
	minWidth: '20rem',
}
const cssFieldColumnContainer = {
	display: 'flex',
	flexDirection: 'column',
	backgroundColor: '#DDD',
	padding: '0.5rem',
	border: '1px solid #999',
	borderRadius: '0.2rem'
}
const cssGridFieldContainer = {
	display: 'grid',
	gridTemplateColumns: "1fr 1fr 1fr 1fr",
	columnGap: '1rem',
	rowGap: '0.4rem',
	marginBottom: '1.5rem'
}
const cssButtonContainer = {
	display: 'flex',
	gap: '1rem',
	justifyContent: 'flex-end'
}

const StudentEditor = ({value, close, defaultSiteId}) => {
	const [email, setEmail] = useState(value.email || "")
	const [id, setId] = useState(value.id || "")
	const [firstName, setFirstName] = useState(value.firstName || "")
	const [firstNameAlias, setFirstNameAlias] = useState(value.firstNameAlias || "")
	const [lastName, setLastName] = useState(value.lastName || "")
	const [grade, setGrade] = useState(value.grade || "")
	const [active, setActive] = useState(value.active)
	const [siteId, setSiteId] = useState(value.siteId ? value.siteId : defaultSiteId)

	const {sites} = useTracker(async () => {
		let sites = await Sites.find({}).fetch();

		return {sites}
	});
	
	if(!siteId && sites && sites.length > 0) {
		setSiteId(sites[0]._id)
	}

	const applyChanges = async () => {
		close()
		//TODO Should invert this and only close if there was success on the server.
		if(value._id)
			await Meteor.callAsync("students.update", value._id, id, firstName, firstNameAlias, lastName, email, siteId, grade, active);
		else
			await Meteor.callAsync("students.add", id, firstName, firstNameAlias, lastName, email, siteId, grade, active);
	}
	const rejectChanges = () => {
		close()
	}

	return (
		<div style={cssFieldColumnContainer}>
			<h1>Student Editor</h1>
			<div style={cssGridFieldContainer}>
				<TextField variant="standard" label="ID" value={id} onChange={(e) => {setId(e.target.value)}}/>
				<TextField variant="standard" label="Email" value={email} onChange={(e) => {setEmail(e.target.value)}}/>
				<TextField variant="standard" label="Grade" value={grade} onChange={(e) => {setGrade(e.target.value)}}/>
				<FormControlLabel control={<Switch variant="standard" checked={active} onChange={(e) => {setActive(e.target.checked)}}/>} label="Active"/>
				<TextField variant="standard" label="First Name" value={firstName} onChange={(e) => {setFirstName(e.target.value)}}/>
				<TextField variant="standard" label="Alias" value={firstNameAlias} onChange={(e) => {setFirstNameAlias(e.target.value)}}/>
				<TextField variant="standard" label="Last Name" value={lastName} onChange={(e) => {setLastName(e.target.value)}}/>
				<TextField select variant="standard" label="Site" value={siteId} onChange={(e) => {setSiteId(e.target.value)}}>
					{sites.map((next, i) => {
						return <MenuItem key={next._id} value={next._id}>{next.name}</MenuItem>
					})}
				</TextField>
			</div>
			<div style={cssButtonContainer}>
				<Button variant="contained" className="button accept-button" onClick={applyChanges}>Accept</Button>
				<Button variant="outlined" className="button reject-button" onClick={rejectChanges}>Reject</Button>
			</div>
		</div>
	)
}

export default () => {
	const siteAll = {_id: 0, name: "All"}
	const [site, setSite] = useState(siteAll._id)

	Meteor.subscribe('sites');
	Meteor.subscribe('students');

	const {sites} = useTracker(async () => {
		const sites = await Sites.find({}).fetchAsync();

		sites.push(siteAll);

		return {sites}
	});

	const ACTIVE_BOTH = "both"
	const ACTIVE_ONLY = "active"
	const ACTIVE_OFF = "inactive"
	const [active, setActive] = useState(ACTIVE_BOTH)
	const [nameSearch, setNameSearch] = useState("")

	const {students} = useTracker(async () => {
		const studentQuery = site === siteAll._id ? {} : {siteId: site}
		
		if(active !== ACTIVE_BOTH) {
			studentQuery["active"] = active === ACTIVE_ONLY
		}
		
		if(nameSearch && nameSearch.length > 2) {
			studentQuery["$or"] = [{firstName: {$regex: nameSearch, $options: 'i'}}, {firstNameAlias: {$regex: nameSearch, $options: 'i'}}, {lastName: {$regex: nameSearch, $options: 'i'}}]
		}
		
		let students = await Students.find(studentQuery).fetchAsync();

		return {students}
	});

	const columns = [
		{
			name: "ID",
			value: (row) => row.id,
			descendingComparator: (a, b) => {
				if(a.id === b.id) return 0
				else if(!a.id) return -1
				else if(!b.id) return 1
				else if(a.id.length < b.id.length) return 1
				else if(a.id.length > b.id.length) return -1
				else if(b.id < a.id) return -1
				else return 1
			}
		},
		{
			name: "Email",
			value: (row) => row.email,
		},
		{
			name: "First Name",
			value: (row) => row.firstName,
		},
		{
			name: "Alias",
			value: (row) => row.firstNameAlias,
		},
		{
			name: "Last Name",
			value: (row) => row.lastName,
		},
		{
			name: "GRD",
			value: (row) => row.grade,
			descendingComparator: (a, b) => {
				if(a.grade === b.grade) return 0
				else if(!a.grade) return -1
				else if(!b.grade) return 1
				else if(a.grade.length < b.grade.length) return 1
				else if(a.grade.length > b.grade.length) return -1
				else if(b.grade < a.grade) return -1
				else return 1
			}
		},
		{
			name: "Active",
			value: (row) => row.active ? "Active" : "Inactive",
		},
	]

	const options = {
		key: (row) => row._id,
		editor: (row, close) => {return (<StudentEditor value={row} close={close} defaultSiteId={site}/>)},
		add: true,
		maxHeight: '40rem',
		keyHandler: (e, selected) => {
			if(selected && selected._id && e.key === "Delete") {
				Meteor.call("students.remove", selected._id);
			}
		}
	}
	
	const importData = (type) => {
		let input = document.createElement('input')
		input.type = 'file'
		input.onchange = _ => {
			let files = Array.from(input.files)

			if(files.length === 1) {
				let reader = new FileReader()
				reader.onload = () => {
					Meteor.call("students.loadCsv", reader.result, type, testImportOnly, (err, result) => {
						//Note: It would be nice to have feedback about the operation, but right now I cannot figure out how to wait on the server for the result of the callback that is wrapped by a bindEnvironment call.
						if(err) console.log(err)
						// else if(testImportOnly) console.log(result)
					})
				}
				reader.readAsText(input.files[0])
			}
		}
		input.click()
	}
	
	const [showImportDialog, setShowImportDialog] = useState(false)
	const [testImportOnly, setTestImportOnly] = useState(false)
	
	const openImportDialog = () => {
		setTestImportOnly(false)
		setShowImportDialog(true)
	}
	const closeImportDialog = (cause, importType) => {
		if(importType) importData(importType)

		if(showImportDialog) setShowImportDialog(false)
	}
	
	return (
		<>
			<Dialog open={showImportDialog}>
				<DialogTitle>Import</DialogTitle>
				<DialogContent style={{display: 'flex', flexDirection: 'column'}}>
					<p>Imports students for the entire district and deals with altering the "active" flag for students no longer in the district or who have graduated.</p>
					<h3>Middle of Year</h3>
					<pre>LIST STU SC ID SEM FN LN GR FNA</pre>
					<p>Run any time during the year to capture changes in student body.</p>
					<h3>End of Year</h3>
					<pre>LIST STU NS ID SEM FN LN NG FNA IF NG &gt;= 12</pre>
					<p>Use this query for the import if the school year is over (before summer school).  It utilizes the next school &amp; next grade fields instead of the current grade/school.</p>
					<FormControlLabel control={<Checkbox checked={testImportOnly} onChange={(e) => setTestImportOnly(e.target.checked)}/>} label="Test Only"/>
				</DialogContent>
				<DialogActions>
					<Button onClick={() => closeImportDialog("button")}>Cancel</Button>
					<Button onClick={() => closeImportDialog("button", 'csv')}>Import CSV</Button>
					<Button onClick={() => closeImportDialog("button", 'aeries-txt')}>Import Aeries TXT</Button>
				</DialogActions>
			</Dialog>
			
			<Box component="div" sx={{m: 2, p: 2, border: '1px dashed grey'}}>
				<TextField label="Site" style={cssSitesSelect} select variant="standard" value={site} onChange={(e)=>{setSite(e.target.value)}}>
					{sites.map((next, i) => {
						return <MenuItem key={next._id} value={next._id}>{next.name}</MenuItem>
					})}
				</TextField>
				<Box component="div" sx={{display: "inline-block", marginLeft: "2rem"}}>
					<InputLabel htmlFor="activeGroup" sx={{fontSize: "0.8rem"}}>Active Students</InputLabel>
					<ToggleButtonGroup id="activeGroup" color="primary" value={active} exclusive onChange={(e)=>{setActive(e.target.value)}} aria-label="Active Students">
						<ToggleButton value={ACTIVE_BOTH}>All</ToggleButton>
						<ToggleButton value={ACTIVE_ONLY}>Active</ToggleButton>
						<ToggleButton value={ACTIVE_OFF}>Inactive</ToggleButton>
					</ToggleButtonGroup>
				</Box>
				<TextField sx={{margin: "0.7rem 0 0 2rem"}} variant="standard" label="Name Search" value={nameSearch} onChange={(e) => {setNameSearch(e.target.value)}}/>
				<Box component="div" sx={{display: "inline-block", float: "right", marginTop: "1rem"}}>
					<Button variant="contained" color='secondary' className="button" onClick={openImportDialog}>Import</Button>
				</Box>
			</Box>
			<SimpleTable rows={students} columns={columns} options={options}/>
		</>
	)
}