
document.addEventListener('DOMContentLoaded', account_embed_onload_function);
function account_embed_onload_function() {
	// console.log("account_embed loaded");
	return;
	setTimeout(() => {
		let byte_ui_modal = new byteUIModal({
			textTitle: "Delete this page Shortcut?",
			textDesc: "",
			buttons: {
				'button_1': {'text': 'Yes','class': 'button tiny primary','action': async function() {
					await shouldInitialize('something!');
					console.log('yes');
					byte_ui_modal.close()
					return;
					fetch('/admin/api/account_settings/remove_shortcuts', {
						method: 'POST',
						headers: {"Content-Type": "application/x-www-form-urlencoded"},
						body: new URLSearchParams({url: shortcutUrl}).toString(),
					})
					.then( response => {
						if (!response.ok) { 
							throw new Error('Network response was not ok', response);
							return;
						} else return response.json();//fix me please and put back into javascript.json
					})
					.then((response) => {
						byte_ui_modal.close();// remove bs modal
						let flash_byte_ui_modal = new byteUIModal({textTitle: "Shortcut has been removed", textDesc: "", buttons: "", inputs: "", flashOnly: true, flashTimeout: 3000});
						flash_byte_ui_modal.flash();
						//ql_list_item.remove();
						//setTimeout(function(){location.reload();},300);// timeout till page reload
					})
					.catch((err) => {
						console.error('Fetch Error ', err);
					});
				}},
				'button_2': {'text': 'Cancel','class': 'button tiny secondary','action': function() {
					byte_ui_modal.close();// remove bs modal
				}},
			},
			// inputs: ["test"]
		});
		byte_ui_modal.open();
		// byte_modal.flash('success','This is a test of the new flash system!', 'Click me to dismiss me.');
	}, 1000)
	setTimeout(() => {
		let byte_modal = new byteUIModal();
		byte_modal.flash('warning','Some second one!');
	}, 2000)

}
async function shouldInitialize(which) {
	console.log('shouldInitialize', which);
	let returnthing = await otherFunction(which);
	console.log('returnthing', returnthing);
}
async function otherFunction(which) {
	console.log('otherFunction', which);
	await new Promise(resolve => setTimeout(resolve, 2000));
	return 'testy';
}


/**
 * AccountEmbed class
 * 
 * There are four modes to the account system: 
 * - straight API calls (/auth/api/login) which doesn't use this object at all, 
 * - object methods to call from outside js file like my_account_embed.login(email, password),
 * - form mode from outside js file which creates/shows/hides the forms in the DOM and hooks up the actions, like submitFormLogin, and
 * - full embed mode, where the forms and actions are all created dynamically and employes three previous modes
 * 
 * Still trying to get jsdoc to be accurate, have a front end, and be readable in vscode https://jsdoc.app/howto-es2015-classes
 */
class AccountEmbed {
	/**
	 * @param {object} options - options for the account embed system, specifically:
	 * @param {boolean} options.autocheck_login - whether to check if the user is logged in on page load
	 * @param {string} options.attach_to_element - where to attach the account menus
	 * @param {string} options.embed_placement - how to place the embed form, either 'inline', 'menu' (TODO) or 'overlay'
	 * @param {boolean} options.refresh_after_login - whether to refresh the page after login
	 * @param {string} options.location_on_login - where to go after login
	 * 
	 * @hooks {function} options.onAutoCheckLogin - hook for when the autocheck_login is done
	 * @hooks {function} options.onLogin - hook for when the user logs in
	 * @hooks {function} options.onRegister - hook for when the user registers
	 * @hooks {function} options.onForgotPw - hook for when the user forgets their password
	 * @hooks {function} options.onResetPwByCode - hook for when the user resets their password by code
	 * @hooks {function} options.onLogout - hook for when the user logs out
	 * @hooks {function} options.onSettings - hook for when the user changes their settings
	 */

    constructor(options) {
        let defaults = {
			autocheck_login: true,
			attach_to_element: 'body',
			embed_placement: 'inline',
			refresh_after_login: false,
			location_on_login: false,
		};
        this.options = Object.assign(defaults, options);
		this.userIsLoggedIn = false;
		if (this.options.autocheck_login) {
			// make a nice quick check in an asycn to see what menu to paint
			(async () => {
				let response = await this.checkAccountStatus();
				if (this.options.onAutoCheckLogin) { // connect object hooks
					this.options.onAutoCheckLogin(response);
				}
			})();
		}
	}

	/**
	 * Checks account status by doing an api call to /auth/api/me
	 * @returns {object} of status, like {"status":"error","message":"User is not logged in"} or {"status": "success", "message": "","data": {...}}
	 */
	checkAccountStatus = () => {
		console.log('> checkAccountStatus');
		// get the user's status
		return fetch('/auth/api/me', {
			method: 'GET',
			})
			.then(res=>res.json())//fix me please and put back into javascript.json
			.then((response) => {
				// console.log('Response:', response);
				if (response.status == 'success') {
					this.userIsLoggedIn = true;
				} else if (response.status == 'error') {
					this.userIsLoggedIn = false;
				}
				return response;
			}
		)
		.catch(function(err) {
			console.log('Fetch Error :-S', err);
			let byte_modal_flash = new byteUIModal();
			byte_modal_flash.flash("error", "An unknown error occured, refresh the page." ,"If this persists, please contact support.");
		});
	}

	/**
	 * Attach the login menu to the DOM
	 */
	attachLoginMenu = () => {
		console.log('open');
		var account_div = document.createElement('div');
		// account_div.style.position = 'relative';
		// account_div.insertAdjacentHTML('beforeend', `
		// 	<button id="account-embed-login" onclick="showAccountMenuForm('embed')">Login</button>
		// `);
		let embed_html =`
			<div id="account-embed-layout" class="account-embed-layout account-embed-hidden">
				<div class="account-embed-inside">
					<form id="account-embed-login-form" method="post">
						<p id="account-embed-login-form-title">Sign in or <button type="button" class="account-embed-link-like" id="account-embed-login-form-create-account">create an account</button></p>
						<label><span>Email:</span><input type="text" name="email" id="account-embed-login-form-email" autocomplete="email" placeholder="me@example.com"></label>
						<label><span>Password:</span><input type="password" name="pw" id="account-embed-login-form-pw" autocomplete="current-password" placeholder="Password"></label>
						<button type="submit">Login</button>
						<button type="button" class="account-embed-link-like" id="account-embed-login-form-forgot-pw">Forgot Password</button>
					</form>
					<form id="account-embed-forgot-pw-form" method="post" class="account-embed-hidden">
						<p id="account-embed-login-form-title">Forgot password or <button type="button" class="account-embed-link-like" id="account-embed-forgot-pw-form-login">back to login</button></p>
						<label><span>Email:</span><input type="text" name="email" id="account-embed-forgot-pw-form-email" placeholder="me@example.com"></label>
						<button type="submit">Send reset code via email</button>
					</form>
					<form id="account-embed-reset-pw-by-code-form" method="post" class="account-embed-hidden">
						<p id="account-embed-login-form-title">Password code sent. Enter here to reset your password. (or <button type="button" id="account-embed-reset-pw-by-code-login" class="account-embed-link-like">cancel</button>)</p>
						<label><span>Email:</span><input type="text" disabled name="email" autocomplete="username" id="account-embed-reset-pw-by-code-email"></label>
						<label><span>Password code (from email):</span><input type="text" name="reset_pw_code" autocomplete="off" id="account-embed-reset-pw-by-code-code" placeholder="Reset Code (from email)"></label>
						<label><span>Password:</span><input type="password" name="password" autocomplete="new-password" id="account-embed-reset-pw-by-code-pw" placeholder="New password"></label>
						<label><span>Confirm password:</span><input type="password" name="confirm_password" autocomplete="new-password" id="account-embed-reset-pw-by-code-pw-confirm" placeholder="Confirm new password"></label>
						<button type="submit">Update password</button>
					</form>
					<form id="account-embed-register-form" method="post" class="account-embed-hidden">
						<p id="account-embed-register-form-title">Create Account or <button type="button" class="account-embed-link-like" id="account-embed-register-form-login">sign in</button></p>
						<label><span>Email:</span><input type="text" name="email" id="account-embed-register-form-email" autocomplete="email" placeholder="me@example.com"></label>
		`;
		// console.log('fields', fields);
		for (const key in fields) {
			// console.log('key', key, fields[key]);
			embed_html += `		<label><span>${fields[key]['label']}:</span><input type="text" name="${key}" autocomplete="${fields[key]['autocomplete']}" id="account-embed-register-form-${key}" placeholder="${fields[key]['label']}"></label>\n`;
		}
		embed_html += `
						<label><span>Password:</span><input type="password" name="password" autocomplete="new-password" id="account-embed-register-form-pw" placeholder="Password"></label>
						<label><span>Confirm password:</span><input type="password" name="confirm_password" autocomplete="new-password" id="account-embed-register-form-pw-confirm" placeholder="Confirm password"></label>
						<button id="account-embed-register-submit" type="submit">Create Account</button>
					</form>
					<p class="account-embed-messages"></p>
				</div>
			</div>
		`;
		// start styles
		embed_html += `
			<style>
				.account-embed-hidden { display:none; }
				.account-embed-layout * { box-sizing: border-box;margin:0; }
				.account-embed-layout { position:absolute;right:0;top:33px;width:300px;background-color:white;border:1px solid black;padding:10px; }
				.account-embed-layout p { margin-bottom:5px; }
				.account-embed-layout p.account-embed-messages { margin-top:5px;margin-bottom:0;color:red; }
				.account-embed-layout p.account-embed-messages.account-embed-messages-error { color:red; }
				.account-embed-layout input { width:100%;padding:5px;margin-bottom:5px; }
				.account-embed-link-like { background-color:transparent;padding:0;border:none;text-decoration:underline;cursor:pointer; }
				.account-embed-inside label { display:block;margin: 3px 0; }
				.account-embed-inside label > span { display:block;font-size:11px;padding-bottom:3px;color:#888;text-transform:uppercase; }
				.account-embed-login-form-title { margin:0;font-weight: bold; }
			</style>
		`;
		console.log('this.embed_placement', this.options.embed_placement);
		if (this.options.embed_placement == 'overlay') {
			embed_html += `
				<style>
					.account-embed-layout { box-sizing: border-box;position:fixed;right:0;top:0;bottom:0;width:100%;background-color:#fffc;border:1px solid black;padding:10px; }
					.account-embed-inside { max-width:300px;margin:20px auto;background-color:white;border:1px solid black;padding:10px; }
				</style>
			`;
		}
		account_div.insertAdjacentHTML('beforeend', embed_html);
		// let fields_to_insert_loc = account_div.getElementById('account-embed-register-form');
		// console.log('fields_to_insert_loc', fields_to_insert_loc);
		// console.log('???', this.options.attach_to_element, this.options.embed_placement);
		document.querySelector(this.options.attach_to_element).appendChild(account_div);
		// document.getElementById('account-embed').appendChild(account_div);
		// hook up buttons to actions
		document.getElementById('account-embed-login-form-create-account').addEventListener('click', () => this.showAccountMenuForm('register'));
		document.getElementById('account-embed-login-form-forgot-pw').addEventListener('click', () => this.showAccountMenuForm('forgot-pw'));
		document.getElementById('account-embed-forgot-pw-form-login').addEventListener('click', () => this.showAccountMenuForm('login'));
		document.getElementById('account-embed-register-form-login').addEventListener('click', () => this.showAccountMenuForm('login'));
		document.getElementById('account-embed-reset-pw-by-code-login').addEventListener('click', () => this.showAccountMenuForm('login'));
		// hook up forms to actions
		document.getElementById('account-embed-login-form').addEventListener('submit', (e) => this.submitFormLogin(e));
		document.getElementById('account-embed-register-form').addEventListener('submit', (e) => this.submitFormRegister(e));
		document.getElementById('account-embed-forgot-pw-form').addEventListener('submit', (e) => this.submitFormForgotPw(e));
		document.getElementById('account-embed-reset-pw-by-code-form').addEventListener('submit', (e) => this.submitFormResetPwByCode(e));
	}
	attachUserMenu = () => {
		console.log('> showUserMenu');
		// document.querySelector(this.options.attach_to_element).innerHTML = '';

		var account_div = document.createElement('div');
		// account_div.style.position = 'relative';
		// account_div.insertAdjacentHTML('beforeend', `
		// 	<button id="account-embed-menu"><span class="account-actions-visually-hidden">Account</span></button>
		// `);
		let embed_html =`
		<div id="account-embed-layout" class="account-actions-layout account-embed-hidden">
			<div class="account-actions-inside">
				<ul>
					<li>
						<button class="account-actions-settings-button account-embed-link-like" id="account-actions-settings-button"><i class="fa fa-cog"></i> Account settings</button>
						<div id="account-embed-settings-form" class="account-actions-settings account-embed-hidden">
							<form id="account-embed-reset-pw-form" method="post">
								<p class="account-embed-login-form-title">Change password</p>
								<label><span>Current password:</span><input type="password" name="current_password" autocomplete="current-password" id="account-embed-reset-pw-old-pw" placeholder="Current password"></label>
								<label><span>New password:</span><input type="password" name="new_password" autocomplete="new-password" id="account-embed-reset-pw-new-pw" placeholder="New password"></label>
								<label><span>Confirm new password:</span><input type="password" name="new_confirm_password" autocomplete="new-password" id="account-embed-reset-pw-new-pw-confirm" placeholder="Confirm new password"></label>
								<button type="submit">Update password</button>
							</form>
							<p class="account-embed-messages"></p>
						</div>
					</li>
					<li>
						<button class="account-embed-link-like" id="account-actions-layout-button"><i class="fa fa-user"></i> Log Out</button>
					</li>
				</ul>
			</div>
		</div>
	
		<style>
			#account-embed { width:37px;height:37px;margin-top:2px;margin-right: 10px;border:0; background-image:url('//www.gravatar.com/avatar/ed535b7db3656b3fba9e3fd6a238e1dc?d=retro&amp;s=200');background-size:cover;border-radius:30px; }
			#account-embed-login { width:37px;height:37px;background-color:transparent;border:0;cursor:pointer; }
			.account-embed-hidden { display:none; }
			.account-actions-layout * { box-sizing: border-box; }
			.account-actions-layout { position:absolute;right:-10px;top:33px;width:200px;background-color:white;border:1px solid black;padding:0px; }
			.account-actions-layout ul { list-style-type: none; padding: 0; margin: 0; }
			.account-actions-layout li { border-bottom: 1px solid #ccc; }
			.account-actions-layout li button.account-embed-link-like { width: 100%;background-color:transparent;border:0;display:block;padding: 5px 10px;text-align:left; }
			.account-actions-layout li button.account-embed-link-like:hover { background-color:#ececec; }
			.account-actions-layout p.account-embed-messages { margin-top:5px;margin-bottom:0;color:red; }
			.account-actions-layout p.account-embed-messages.account-embed-messages-error { color:red; }
			/*.account-actions-visually-hidden { border: 0;clip: rect(0 0 0 0);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px; }*/
			.account-actions-settings-button:after { content: '▸';float: right; }
			.account-actions-settings-button-open:after { content: '▾';float: right; }
			.account-actions-settings { background-color: #f8f8f8;border-top: 1px solid #ccc;padding:10px; }
			.account-actions-inside label { display:block;margin: 3px 0; }
			.account-actions-inside label > span { display:block;font-size:11px;padding-bottom:3px;color:#888;text-transform:uppercase; }
			.account-embed-login-form-title { margin:0;font-weight: bold; }
		</style>
		`;
		if (this.options.embed_placement == 'overlay') {
			embed_html += `
				<style>
					.account-actions-layout { box-sizing: border-box;position:fixed;right:0;top:0;bottom:0;width:100%;background-color:#fffc;border:1px solid black;padding:10px; }
					.account-actions-inside { max-width:300px;margin:20px auto;background-color:white;border:1px solid black;padding:10px; }
					.account-actions-layout ul { background-color:#fcfcfc;border: 1px solid #ccc; border-bottom: none; }
				</style>
			`;
		}
		account_div.insertAdjacentHTML('beforeend', embed_html); 
		// let fields_to_insert_loc = account_div.getElementById('account-embed-register-form');
		// console.log('fields_to_insert_loc', fields_to_insert_loc);
		// console.log('???', this.options.attach_to_element, document.querySelector(this.options.attach_to_element));
		// remove 
		// document.querySelector(this.options.attach_to_element).innerHTML = '';
		document.querySelector(this.options.attach_to_element).appendChild(account_div);
		// activate buttons
		// document.getElementById('account-embed-menu').addEventListener('click', () => this.account_embed_show_menu());
		document.getElementById('account-actions-layout-button').addEventListener('click', () => this.submitFormLogout());
		document.getElementById('account-actions-settings-button').addEventListener('click', () => this.showAccountMenuForm('settings'));
		// form submission
		document.getElementById('account-embed-reset-pw-form').addEventListener('submit', (e) => this.submitFormResetPw(e));
	}

	eventListenerCloseOverlay = (e) => {
		if (e.key === "Escape" || e.target.id == 'account-embed-layout') {
			console.log('Close form', e);
			this.toggleAccountMenu(e);
		}
	}
	toggleAccountMenu = (e) => {
		console.log('> toggleAccountMenu');
		// are we opening or closing?
		let currently_opening_menu = document.getElementById('account-embed-layout').classList.contains('account-embed-hidden');
		if (currently_opening_menu) {
			console.log('currently closed, opening');
			if (this.options.embed_placement == 'overlay') {
				// set up event listeners to close overlay
				console.log('add event listeners');
				window.addEventListener('keydown', this.eventListenerCloseOverlay);
				document.getElementById('account-embed-layout').addEventListener('click', this.eventListenerCloseOverlay);
			}
		} else {
			console.log('currently open, closing now');
			//			this.eventListenerCloseOverlay({key: "Escape"});// faking that the escape key was pressed
			if (e.key === "Escape" || e.target.id == 'account-embed-layout') {
				console.log('Close form', e);
				// remove event listeners
				window.removeEventListener('keydown', this.eventListenerCloseOverlay);
				document.getElementById('account-embed-layout').removeEventListener('click', this.eventListenerCloseOverlay);
				console.log('Removed event listeners', e);
			}
		}
		// toggle embed layout
		document.getElementById('account-embed-layout').classList.toggle('account-embed-hidden');
		// reset subforms if we're logged in
		if (!this.userIsLoggedIn) {
			// console.log('User is not logged in');
			// clear messages and reset subforms
			document.querySelector('.account-embed-messages').innerHTML = '';
			document.querySelector('.account-embed-messages').classList.remove('account-embed-messages-error');
			document.getElementById('account-embed-login-form').classList.remove('account-embed-hidden');
			document.getElementById('account-embed-forgot-pw-form').classList.add('account-embed-hidden');
			document.getElementById('account-embed-register-form').classList.add('account-embed-hidden');
		}
	}
	showAccountMenuForm(action) {
		console.log('switch to ' + action);
		// clear messages and reset subforms
		if (this.userIsLoggedIn) {
			console.log('Logged in');
			// if (action == 'settings') {
				// show account settings
				document.getElementById('account-embed-settings-form').classList.toggle('account-embed-hidden');
			// }
		} else {
			console.log('not logged in');
			// clear messages and reset subforms
			document.querySelector('.account-embed-messages').innerHTML = '';
			document.querySelector('.account-embed-messages').classList.remove('account-embed-messages-error');
			document.getElementById('account-embed-login-form').classList.add('account-embed-hidden');
			document.getElementById('account-embed-forgot-pw-form').classList.add('account-embed-hidden');
			document.getElementById('account-embed-register-form').classList.add('account-embed-hidden');
			// logic for showing form
			if (action == 'embed') {
				// toggle the global embed form and show the login subform
				document.getElementById('account-embed-layout').classList.toggle('account-embed-hidden');
				document.getElementById('account-embed-login-form').classList.remove('account-embed-hidden');
			} else {
				// show subform for action
				document.getElementById('account-embed-'+action+'-form').classList.remove('account-embed-hidden');
			}
		}
	}

	/**
	 * login form submission (to be used inside or outside class)
	 * @param {Event} e -- a form submission event so we can prevent default
	 */
	submitFormLogin = async (e) => {
		console.log('> submitFormLogin');
		e.preventDefault();

		let response = await this.login(document.getElementById('account-embed-login-form-email').value, document.getElementById('account-embed-login-form-pw').value);
		console.log('response', response);

		if (response.status == 'success') {
			document.querySelector('.account-embed-messages').innerHTML = 'Successfully logged in.';
			setTimeout(() => {
				// should we go somewhere or refreesh or stay here?
				if (this.location_on_login) {
					window.location.href = this.location_on_login;
				} else if (this.refresh_after_login) {
					window.location.reload();
				} else {
					// we're staying right here, not refreshing or going anywhere, so close the form
					this.userIsLoggedIn = true;
					this.toggleAccountMenu({key: "Escape"});// faking that the escape key was pressed
					// this.account_embed_close_form({key: "Escape"});// faking that the escape key was pressed
					console.log('Logged in now...whats next');
					if (this.options.onLogin) { // connect object hooks
						this.options.onLogin(response, 'login');
					}
				}
			}, 1000);
		}
		if (response.status == 'error') {
			document.querySelector('.account-embed-messages').innerHTML = Object.keys(response.errors).map(function(x){return response.errors[x][1];}).join(', ');
			document.querySelector('.account-embed-messages').classList.add('account-embed-messages-error');
		}
	}

	/**
	 * login form submission (to be used inside or outside class)
	 * @param {*} email 
	 * @param {*} password 
	 * @returns success or error object, with error messages
	 */
	login = (email, password) => {
		console.log('> login');
		if (!email.trim() || !password.trim()) {
			return 
		}
		return fetch('/auth/api/login', {
			method: 'POST',
			headers: {"Content-Type": "application/x-www-form-urlencoded"},
			body: new URLSearchParams({
					email: email,
					pw: password,
					token: csrf_token
				}).toString()
			})
			.then(res=>res.json())//fix me please and put back into javascript.json
			.then((response) => {
				console.log('Response:', response);
				return response;
			}
		)
		.catch(function(err) {
			console.log('Fetch Error :-S', err);
			let byte_modal_flash = new byteUIModal();
			byte_modal_flash.flash("error", "An unknown error occured, refresh the page." ,"If this persists, please contact support.");
		});
	};

	// register form submission
	submitFormRegister = async(e) => {
		console.log('> submitFormRegister');
		e.preventDefault();
		// set up extra fields from global fields list
		let extra_fields_array = {};
		for (const key in fields) {
			// console.log('key', key, fields[key]);
			extra_fields_array[key] = document.getElementById('account-embed-register-form-'+key).value;
		}
		// call the regular method
		let response = await this.register(document.getElementById('account-embed-register-form-email').value, document.getElementById('account-embed-register-form-pw').value, document.getElementById('account-embed-register-form-pw-confirm').value, extra_fields_array);
		if (response.status == 'success') {
			document.querySelector('.account-embed-messages').innerHTML = 'Successfully created account and logged in.';
			setTimeout(() => {
				// should we go somewhere or refreesh or stay here?
				if (this.location_on_login) {
					window.location.href = this.location_on_login;
				} else if (this.refresh_after_login) {
					window.location.reload();
				} else {
					// we're staying right here, not refreshing or going anywhere, so close the form
					this.userIsLoggedIn = true;
					this.toggleAccountMenu({key: "Escape"});// faking that the escape key was pressed
					// this.account_embed_close_form({key: "Escape"});// faking that the escape key was pressed
					console.log('Logged in now...whats next');
					if (this.options.onRegister) { // connect object hooks
						this.options.onRegister(response);
					}
					if (this.options.onLogin) { // connect object hooks
						this.options.onLogin(response, 'register');
					}
				}
			}, 1000);
		}
		if (response.status == 'error') {
			document.querySelector('.account-embed-messages').innerHTML = Object.keys(response.errors).map(function(x){return response.errors[x][1];}).join(', ');
			document.querySelector('.account-embed-messages').classList.add('account-embed-messages-error');
		}

	}
	/**
	 * 
	 * @param {*} email 
	 * @param {*} pw 
	 * @param {*} pw_confirm 
	 * @param {*} extra_fields_array including any fields in the global fields object, from config
	 * 
	 * @returns success or error object, with error messages
	 */
	register(email, pw, pw_confirm, extra_fields_array) {
		console.log('> register');
		// start fields object with required fields
		let fields_to_insert = {
			email: email,
			pw: pw,
			pw_confirm: pw_confirm,
			token: csrf_token
		}
		// add any extra fields
		fields_to_insert = {...fields_to_insert, ...extra_fields_array};
		// add config-defined fields
		for (const key in fields) {
			console.log('key', key, fields[key]);
			fields_to_insert[key] = document.getElementById('account-embed-register-form-'+key).value;
		}
		return fetch('/auth/api/register', {
			method: 'POST',
			headers: {"Content-Type": "application/x-www-form-urlencoded"},
			body: new URLSearchParams(fields_to_insert).toString()
			})
			.then(res=>res.json())//fix me please and put back into javascript.json
			.then((response) => {
				console.log('Response:', response);
				return response;
			}
		)
		.catch(function(err) {
			console.log('Fetch Error :-S', err);
			let byte_modal_flash = new byteUIModal();
			byte_modal_flash.flash("error", "An unknown error occured, refresh the page." ,"If this persists, please contact support.");
		});
	};

	// forgot password form submission
	submitFormForgotPw = async(e) => {
		console.log('> submitFormForgotPw');
		e.preventDefault();
		// get field
		let forgot_pw_email = document.getElementById('account-embed-forgot-pw-form-email').value;
		// sanitize email for xss
		forgot_pw_email = forgot_pw_email.replace(/[\u00A0-\u9999<>\&]/g, i => '&#'+i.charCodeAt(0)+';').trim();
		// call the regular method
		let response = await this.forgotPw(forgot_pw_email);
		if (response.status == 'success') {
			document.querySelector('.account-embed-messages').innerHTML = 'Sent password reset to ' + forgot_pw_email;
			// TODO some safety of loading the same file twice?
			this.showAccountMenuForm('reset-pw-by-code');
			// prefill form with email
			document.getElementById('account-embed-reset-pw-by-code-email').value = forgot_pw_email;
		}
		if (response.status == 'error') {
			document.querySelector('.account-embed-messages').innerHTML = Object.keys(response.errors).map(function(x){return response.errors[x][1];}).join(', ');
			document.querySelector('.account-embed-messages').classList.add('account-embed-messages-error');
		}
	}

	/**
	 * forgot password api call
	 * @param {string} forgot_pw_email -- the email to send the reset code to 
	 * @returns success or error object, with error messages
	 */
	forgotPw(forgot_pw_email) {
		console.log('> forgotPw');

		if (forgot_pw_email) {
			return fetch('/auth/api/forgot_password', {
				method: 'POST',
				headers: {"Content-Type": "application/x-www-form-urlencoded"},
				body: new URLSearchParams({
						email: forgot_pw_email,
						token: csrf_token
					}).toString()
				})
				.then(res=>res.json())//fix me please and put back into javascript.json
				.then((response) => {
					console.log('Response:', response);
					return response;
				}
			)
			.catch(function(err) {
				console.log('Fetch Error :-S', err);
				let byte_modal_flash = new byteUIModal();
				byte_modal_flash.flash("error", "An unknown error occured, refresh the page." ,"If this persists, please contact support.");
			});
		}
	};

	// reset password form submission
	submitFormResetPwByCode = async(e) => {
		console.log('> submitFormResetPwByCode');
		e.preventDefault();
		let response = await this.resetPwByCode(document.getElementById('account-embed-reset-pw-by-code-email').value, document.getElementById('account-embed-reset-pw-by-code-code').value, document.getElementById('account-embed-reset-pw-by-code-pw').value, document.getElementById('account-embed-reset-pw-by-code-pw-confirm').value);
		if (response.status == 'success') {
			document.querySelector('.account-embed-messages').innerHTML = 'Password saved, logging in.';
			// TODO some safety of loading the same file twice?
			setTimeout(() => {
				// should we go somewhere or refreesh or stay here?
				if (this.location_on_login) {
					window.location.href = this.location_on_login;
				} else if (this.refresh_after_login) {
					window.location.reload();
				} else {
					// we're staying right here, not refreshing or going anywhere, so close the form
					this.userIsLoggedIn = true;
					this.toggleAccountMenu({key: "Escape"});// faking that the escape key was pressed
					// this.account_embed_close_form({key: "Escape"});// faking that the escape key was pressed
					console.log('Logged in now...whats next');
					if (this.options.onResetPwByCode) { // connect object hooks
						(async () => {
							await this.options.onResetPwByCode(this);
							if (this.options.onLogin) { // connect object hooks
								this.options.onLogin(response, 'reset_pw_by_code');
							}
						})();
			
					}
				}
			}, 1500);
		}
		if (response.status == 'error') {
			document.querySelector('.account-embed-messages').innerHTML = Object.keys(response.errors).map(function(x){return response.errors[x][1];}).join(', ');
			document.querySelector('.account-embed-messages').classList.add('account-embed-messages-error');
		}
	}

	/**
	 * Reset password by emailed code from forgot pw form
	 * @param {String} reset_pw_email 
	 * @param {String} reset_pw_code 
	 * @param {String} reset_pw_new_pw 
	 * @param {String} reset_pw_new_pw_confirm 
	 * @returns success or error object, with error messages
	 */
	resetPwByCode(reset_pw_email, reset_pw_code, reset_pw_new_pw, reset_pw_new_pw_confirm) {
		console.log('> resetPwByCode');
		// sanitize email for xss
		reset_pw_email = reset_pw_email.replace(/[\u00A0-\u9999<>\&]/g, i => '&#'+i.charCodeAt(0)+';').trim();

		if (reset_pw_email) {
			return fetch('/auth/api/reset_password_by_code', {
				method: 'POST',
				headers: {"Content-Type": "application/x-www-form-urlencoded"},
				body: new URLSearchParams({
						email: reset_pw_email,
						reset_token: reset_pw_code,
						new_pw: reset_pw_new_pw,
						new_pw_confirm: reset_pw_new_pw_confirm,
						csrf_token: csrf_token
					}).toString()
				})
				.then(res=>res.json())//fix me please and put back into javascript.json
				.then((response) => {
					console.log('Response:', response);
					return response;
				}
			)
			.catch(function(err) {
				console.log('Fetch Error :-S', err);
				let byte_modal_flash = new byteUIModal();
				byte_modal_flash.flash("error", "An unknown error occured, refresh the page." ,"If this persists, please contact support.");
			});
		}
	};

	submitFormLogout = async() => {
		let response = await this.logout();
		if (response.status == 'success') {
			this.userIsLoggedIn = false;
			// this.account_embed_close_form({key: "Escape"});// faking that the escape key was pressed
			if (this.options.onLogout) { // connect object hooks
				this.options.onLogout(this);
			}
			console.log('Logged out now...whats next');
			// this.showLoginMenu();
		}
		if (response.status == 'error') {
			// document.querySelector('.account-embed-messages').innerHTML = Object.keys(response.errors).map(function(x){return response.errors[x][1];}).join(', ');
			// document.querySelector('.account-embed-messages').classList.add('account-embed-messages-error');
		}
	}

	/**
	 * Logs the user out via API
	 * @returns success or error object, with error messages
	 */
	logout = () => {
		// console.log('logging out');
		return fetch('/auth/api/logout', {
			method: 'POST',
			headers: {"Content-Type": "application/x-www-form-urlencoded"},
			})
			.then(res=>res.json())//fix me please and put back into javascript.json
			.then((response) => {
				console.log('Response:', response);
				return response;
			}
		)
		.catch(function(err) {
			console.log('Fetch Error :-S', err);
			let byte_modal_flash = new byteUIModal();
			byte_modal_flash.flash("error", "An unknown error occured, refresh the page." ,"If this persists, please contact support.");
		});
	}

	// change password form submission
	submitFormResetPw = async(e) => {
		console.log('> submitFormResetPw');
		e.preventDefault();
		let response = await this.resetPw(document.getElementById('account-embed-reset-pw-old-pw')?.value, document.getElementById('account-embed-reset-pw-new-pw')?.value, document.getElementById('account-embed-reset-pw-new-pw-confirm')?.value);
		if (response.status == 'success') {
			document.querySelector('.account-embed-messages').innerHTML = 'Password updated.';
			setTimeout(() => {
				// reset things
				document.getElementById('account-embed-reset-pw-old-pw').value = '';
				document.getElementById('account-embed-reset-pw-new-pw').value = '';
				document.getElementById('account-embed-reset-pw-new-pw-confirm').value = '';
				// close form
				this.toggleAccountMenu({key: "Escape"});// faking that the escape key was pressed
			}, 1500);
		}
		if (response.status == 'error') {
			document.querySelector('.account-embed-messages').innerHTML = Object.keys(response.errors).map(function(x){return response.errors[x][1];}).join(', ');
			document.querySelector('.account-embed-messages').classList.add('account-embed-messages-error');
		}
	}

	/**
	 * Resets the user's password via API, while logged in
	 * @param {*} reset_pw_old_pw 
	 * @param {*} reset_pw_new_pw 
	 * @param {*} reset_pw_new_pw_confirm 
	 * @returns success or error object, with error messages
	 */
	resetPw(reset_pw_old_pw, reset_pw_new_pw, reset_pw_new_pw_confirm) {
		console.log('> resetPw');

		if (reset_pw_old_pw) {
			return fetch('/auth/api/change_password_by_form', {
				method: 'POST',
				headers: {"Content-Type": "application/x-www-form-urlencoded"},
				body: new URLSearchParams({
						old_pw: reset_pw_old_pw,
						new_pw: reset_pw_new_pw,
						new_pw_confirm: reset_pw_new_pw_confirm,
						csrf_token: csrf_token
					}).toString()
				})
				.then(res=>res.json())//fix me please and put back into javascript.json
				.then((response) => {
					console.log('Response:', response);
					return response;
				}
			)
			.catch(function(err) {
				console.log('Fetch Error :-S', err);
				let byte_modal_flash = new byteUIModal();
				byte_modal_flash.flash("error", "An unknown error occured, refresh the page." ,"If this persists, please contact support.");
			});
		}
	};

}

/**
 * A class for creating flash notifications
 * Some inspiration from https://codeshack.io/interactive-modals-javascript/
 */
flashRecordArray = [];
function byteUIModal(options){
    let _this = this;
	var closeIn = false;
    let defaultOptions = {
		interactivity_exclusivity: false, //TODO: mandate that it is always false for flashes
		container: ".sliderContainer",
		textTitle: "- empty title - (to add title, add textTitle: to the options.)",
		severity: "",// notice, warning, error
		textDesc: "",
		flashOnly: false,
		flashTimeout: 4000, // in milliseconds
		buttons: {
			'button_1': {'text': 'Yes', 'class': 'button tiny primary', 'action': 'alert("You pressed YES")'},
			'button_2': {'text': 'No', 'class': 'button tiny secondary', 'action': 'alert("You pressed NO")'},
		},
		inputs: {
			//'input_1': {'type': 'text', 'id': '', 'placeholder': 'enter in this field', 'style': 'width:100%; margin:0 auto;'},
		},
	}
    options = {...defaultOptions, ...options};

	//record what this flash was for putting into the bell 
	flashRecordArray.push(options);

	flashTimer = null;
	this.setFlashTimer = function(target) {
		console.log('set timer',  options.flashTimeout, target);
		_this.flashTimer = setTimeout(() => {
			_this.close(target);
		}, options.flashTimeout);
	}
	this.clearFlashTimer = function() {
		console.log('clear timer', _this.flashTimer);
		clearTimeout(_this.flashTimer);	
	}

	// allows flash notifications
	this.flash = function(severity = '', title = '', description = '') {
		closeIn = options.flashTimeout;
		options.flashOnly = true;
		if (severity) options.severity = severity;
		if (title) {
			options.textTitle = title;
			options.textDesc = description;
		}
		let thisNotification = this.open();
		this.setFlashTimer(thisNotification);
		// flashTimer = setTimeout(() => {
		// 	this.close(thisNotification);
		// }, closeIn);
	}

	this.open = function() {
		console.log('this.open', this);

		//add viewport click-stopper overlay
		if(options.interactivity_exclusivity){
			if (document.getElementById('byte-ui-modal-exclusivity')) {
				console.log('exclusivity detected ');
				var modalExclusivity = document.getElementById('byte-ui-modal-exclusivity');
			} else {
				console.log('creating exclusivity ');
				var modalExclusivity = document.createElement("div");
				modalExclusivity.setAttribute("id", 'byte-ui-modal-exclusivity');
				document.querySelector('body').appendChild(modalExclusivity);
			}
		}

		//TODO: need keydown + keypress preventers technically

		// Close top vex on escape
		window.addEventListener('keyup', function byteUIModalEventListener (e) {
			if (e.key === 'Escape') {
				window.removeEventListener('keyup', byteUIModalEventListener);
				_this.close();
			}
			else {
				//TODO: restore tab event handling
				if(e.key === 'Tab'){
					console.log('tab event', e);
					// var tab_targets = document.querySelectorAll('#byte-ui-modal > .notification_area.exclusive');
				}
				else if(e.key === 'Shift'){

				}
				//prevent other keyup actions 
				if(options.interactivity_exclusivity){
					e.preventDefault();
					e.stopPropagation();
				}
			}
		})
		if (document.getElementById('byte-ui-modal')) {
			var modalContainer = document.getElementById('byte-ui-modal');
		} else {
			var modalContainer = document.createElement("div");
			modalContainer.setAttribute("id", "byte-ui-modal");
		}
		// modalContainer.setAttribute("class", "byte_clearfix");

        let insideContainer = document.createElement("div");
		insideContainer.setAttribute("class", "notification_area new-class");

		//note that this one is an exclusive
		if(options.interactivity_exclusivity){
			insideContainer.classList.add('exclusive');
		}

		let contentContainer = document.createElement("div");
		contentContainer.setAttribute("class", "content_area");

        let choicesContainer = document.createElement("div");
		choicesContainer.setAttribute("class", "choices_area");
        let textAreaContainer = document.createElement("div");
		textAreaContainer.setAttribute("class", "text_area");
		textAreaContainer.innerHTML = '<strong>'+options.textTitle+'</strong>'+options.textDesc;

		let iconOuterContainer = document.createElement("div");
		iconOuterContainer.setAttribute("class", "icon_area "+options.severity);

		let iconContainer = document.createElement("i");
		iconContainer.setAttribute("class", "fas fa-exclamation-circle");
		iconOuterContainer.appendChild(iconContainer);

		// put them into place
		insideContainer.appendChild(iconOuterContainer);
		// insideContainer.appendChild(textAreaContainer);
		insideContainer.appendChild(contentContainer);
		contentContainer.appendChild(textAreaContainer);
		if (!options.flashOnly && Object.keys(options.buttons).length) textAreaContainer.after(choicesContainer);

		modalContainer.appendChild(insideContainer);
		// console.log(modalContainer);
		document.querySelector('body').appendChild(modalContainer);

		//add an event listener to reset (or pause?) the timer when the container is hovered 

		// var _this = this;
		// this.insideContainer.addEventListener('create', function() { _this.fireEvent('created'); }, false)

		//TODO: fix for flashless ones
		if(options.flashOnly){
			insideContainer.addEventListener("mouseenter", (event) => {
				// console.log('mouse enter');
				_this.clearFlashTimer();
			});
	
			insideContainer.addEventListener("mouseleave", (event) => {
				// console.log('mouse exit');
				_this.setFlashTimer(event.currentTarget);
			});
		}

		// paint buttons
		if (!options.flashOnly) {
			Object.keys(options.inputs).forEach(key => {
				let input_container = document.createElement("div");
				input_container.setAttribute("class", "input_area");
				input_container.setAttribute("style", options.inputs[key].style);

				if (options.inputs[key].label) {
					let input_label = document.createElement("label");
					input_label.setAttribute("for", options.inputs[key].id);
					input_label.innerHTML = options.inputs[key].label;
					input_container.appendChild(input_label);
				}

				let input_attrs = {type: options.inputs[key].type, id: options.inputs[key].id, value: options.inputs[key].value, placeholder: options.inputs[key].placeholder}
				let input = document.createElement("input");
				for (var attr_key in input_attrs) input.setAttribute(attr_key, input_attrs[attr_key]);
				input_container.appendChild(input);

				choicesContainer.appendChild(input_container);
			});

			Object.keys(options.buttons).forEach(key => {
				let button = document.createElement("button");
				button.setAttribute("class", options.buttons[key].class);
				button.addEventListener("click", function(){
					options.buttons[key].action();
				})
				button.textContent = options.buttons[key].text;
				choicesContainer.appendChild(button);
			});
		}
		if (!options.flashOnly && Object.keys(options.buttons).length) choicesContainer.firstChild.focus();// for keyboard nav
		if (closeIn) { // close on click
			insideContainer.addEventListener("click", (e) => {
				console.log('insideContainer click',e.currentTarget);
				this.close(e.currentTarget);
			})
		}


		// setTimeout(() => {
			// console.log('timey whimey');
			// insideContainer.setAttribute("class", "notification_area new-class");
		// }, 10);
		return insideContainer; //use this if you want to close this specific modal later
	}

	this.close = function(which){
		// could add lifecycle stuff here, like onClose()...
		var modalContainer = document.getElementById('byte-ui-modal > .notification_area');
		// which.remove();
		if (which) {

			// set it first to animate
			which.classList.remove('new-class');
			// then when it's done animating, remove it entirely
			setTimeout(() => {
				which.remove();

				//remove viewport click-stopper overlay if there are no other exclusives left
				if(options.interactivity_exclusivity){

					var exclusive_modals = document.querySelectorAll('#byte-ui-modal > .notification_area.exclusive');
					if(typeof exclusive_modals == 'undefined' || exclusive_modals == null || !exclusive_modals.length){
						var modalExclusivity = document.getElementById('byte-ui-modal-exclusivity');
						if (typeof modalExclusivity != 'undefined' && modalExclusivity != null) {
							console.log('remove exclusive overlay');
							modalExclusivity.remove();
						} 
					}
				}

			}, 300);
		} else {
			// we don't know which to remove, so remove them all
			let this_element = document.getElementById('byte-ui-modal');
			this_element.remove();

			//remove viewport click-stopper overlay	
			var modalExclusivity = document.getElementById('byte-ui-modal-exclusivity');
			if (typeof modalExclusivity != 'undefined' && modalExclusivity != null) {
				modalExclusivity.remove();
			} 
			
		}

		// modalContainer.remove();
	}
	this.isLastExclusive = function(){
		var exclusive_modals = document.querySelectorAll('#byte-ui-modal > .notification_area.exclusive');
		if(typeof exclusive_modals != 'undefined' && exclusive_modals != null && exclusive_modals.length == 1 && options.interactivity_exclusivity){
			return true;
		} else return false;
	}
	// this.init();
}


// setTimeout(() => {
// 	let byte_modal = new byteUIModal();
// 	byte_modal.flash('success','This is a test of the new flash system!', 'Click me to dismiss me.');
// }, 1000)
// setTimeout(() => {
// 	let byte_modal = new byteUIModal();
// 	byte_modal.flash('warning','Some second one!');
// }, 2000)


csrf_token = 'zLMx9RFKQ+cLs+aIyPRRl2HFGCEvbu5h0QX0KSokMKM=';
fields = {"s_first_name":{"label":"First Name","autocomplete":"given-name","optional":false,"unique":false},"s_last_name":{"label":"Last Name","autocomplete":"family-name","optional":false,"unique":false},"s_organization":{"label":"Company \/ Organization","autocomplete":"company","optional":true,"unique":false}}
account_embed_logged_in = false;
