import React, { useState, useEffect, useCallback } from 'react';
import { connect } from 'react-redux'
import * as Shared from 'placeholder-shared'
import * as Antd from 'antd'
import { Link, Redirect, withRouter } from 'react-router-dom'
//import * as Common from './common'
import './Login.scss';
import './common.scss';

import { Form, Input, Button, Layout, Row, Col, message, Space, Typography, Card } from 'antd';

import * as Cognito from './Cognito';
import * as Common from './common'
import * as AWSSdk from 'aws-sdk';
import {
	NumberOutlined,
	GoogleOutlined,
	MailOutlined,
	LockOutlined
} from '@ant-design/icons';

const { Meta } = Card;
const userPool = Cognito.getUserPool();

function LayoutComponent(props) {
	const { children } = props;
	return children;
}

function RegisterPage() {
	return (
		<LayoutComponent  ><Register /></LayoutComponent>
	);
}

export const StateRegister = (withRouter(RegisterPage))

function VerifyPage() {
	return (
		<LayoutComponent  > <Verify /></LayoutComponent>
	);
}

export const StateVerify = (withRouter(VerifyPage))

function LoginPage(props) {
	return (
		<LayoutComponent  > <Login /></LayoutComponent>
	);
}

export const StateLogin = (withRouter(LoginPage));

function LogoutPage() {
	return (
		<LayoutComponent  > <Logout /></LayoutComponent>
	);
}

export const StateLogout = (withRouter(LogoutPage));

function HomePage() { //DynamoTag
	return (
		<LayoutComponent><Home /></LayoutComponent>
	)
}

export const StateHome = (withRouter(HomePage))



function ForgotPage() {
	return (
		<LayoutComponent><Forgot /></LayoutComponent>
	);
}

export const StateForgot = (withRouter(ForgotPage))

function ResetPage() {
	return (
		<LayoutComponent><Reset /></LayoutComponent>
	);
}

export const StateReset = (withRouter(ResetPage))


const Register = (props) => {
	const RegisterState = {
		waitingToRegister: 1,
		success: 2,
		failure: 3
	}

	const [registerInfo, setRegisterInfo] = useState({
		username: '',
		email: '',
		password: '',
		confirmPassword: '',
		registerState: RegisterState.waitingToRegister,
		successString: '',
		errorString: ''
	});

	const onChange = e => {
		const { name, value } = e.target;
		setRegisterInfo(registerInfo => registerInfo[name] = value)
	};

	const getRegisterForm = () => {
		const layout = {
			labelCol: { span: 4 },
			wrapperCol: { span: 24 },
		};
		const tailLayout = {
			wrapperCol: { offset: 4, span: 24 },
		};
		const error = (err) => {
			message.error(err);
		};
		const onFinish = values => {
			var user
			Cognito.doRegister(
				userPool,
				values.registerEmailInput,
				values.registerPasswordInput, function (err, msg) {
					if (err) error("error: " + JSON.stringify(err));
					else setRegisterInfo({
						registerState: RegisterState.success,
						successString: "Registered new user " + JSON.stringify(msg)
					})

				}
			)
		};

		const onFinishFailed = errorInfo => {
			console.log('Failed:', errorInfo);
		};
		return <Card hoverable title={<Antd.Typography.Title level={4}>Try Structure</Antd.Typography.Title>}>
		<Form
				style={{ width: '600px' }}
				name="basic"
				initialValues={{ remember: true }}
				onFinish={onFinish}
				onFinishFailed={onFinishFailed}
				className="backgroundWhite flexStay"
			>
				<Form.Item >
					<Antd.Typography.Text level={4}>
					Are you <b>ready</b> to  <em>10X</em> your analytics? 
					</Antd.Typography.Text>
				</Form.Item>
				<Form.Item>
					<Antd.Typography.Text type='secondary'>
						Be sure to join us on&nbsp;
					<a href="https://join.slack.com/t/structuresupport/shared_invite/zt-ddx04ho4-_q43i5o3zQ9jv00qx~dx8A" target="_blank">
							Slack.</a>
					</Antd.Typography.Text>
				</Form.Item>
				<Form.Item
					label=""
					name="registerEmailInput"
					rules={[
						{ required: true, message: 'Please input your email!' },
						{ type: "email", message: 'Please input a valid email address!' }
					]}
				>
					<Input prefix={<MailOutlined  className="site-form-item-icon"/>} className="inputPadding" placeholder={'me@gmail.com'}/>
				</Form.Item>

				<Form.Item
					label=""
					name="registerPasswordInput"
					rules={[
						{ required: true, message: 'Please input your password!' },
						{ min: 8, message: 'Minimum 8 Characters!' },
						{ pattern: /[0-9]/, message: 'At least one number is required!' },
						{ pattern: /[a-z]/, message: 'At least one lowercase character required!' },
						{ pattern: /[A-Z]/, message: 'At least one uppercase character required!' },
						{ pattern: /[!@#$%^&*()\\|\<>\/?,.~`;'"\[\]\{\}]/, message: 'At least one special character required!' }
					]}
				>
					<Input.Password prefix={<LockOutlined className="site-form-item-icon"/>} className="inputPadding" placeholder="*****"/>
				</Form.Item>

			<Form.Item>
				<Button type="primary"  htmlType="submit">Register With Email</Button>
				<Antd.Divider orientation='left' plain>or</Antd.Divider>
				<Button onClick={Cognito.goGoogle}>Register With <GoogleOutlined/>Google</Button>
			</Form.Item>
			</Form>
			</Card>
	}

	const { registerState, username, email, password, confirmPassword } = registerInfo
	return <Common.DivWithClassName className="LoginContainer rowFlexBox flexGrow alignItemsStretch">
		<Common.DivWithClassName className='flexGrow rowFlexBox alignItemsCenter'>
			<Common.DivWithClassName className='rowFlexBox flexGrow justifyContentCenter'>			
				<Common.DivWithClassName className='flexStay rowFlexBox '>
					<Common.DivWithClassName className="colStyle flexStay rowFlexBox " style={{}}>
						{registerState == RegisterState.success &&
							<Redirect to="/account/verify" />
						}
						{registerState == RegisterState.waitingToRegister &&
							getRegisterForm()
						}
					</Common.DivWithClassName>
				</Common.DivWithClassName>
			</Common.DivWithClassName>
		</Common.DivWithClassName>
		</Common.DivWithClassName>
}

function Verify() {
	const VerifyState = {
		waitingToVerify: 1,
		success: 2,
		failure: 3
	}
	const [verifyInfo, setVerifyInfo] = useState({
		username: '',
		email: '',
		verificationCode: '',
		verifyState: VerifyState.waitingToVerify,
		successString: '',
		errorString: ''
	});
	const onChange = e => {
		const { name, value } = e.target;
		setVerifyInfo(verifyInfo => verifyInfo[name] = value)
	};
	const getVerifyForm = () => {
		const layout = {
			labelCol: { span: 8 },
			wrapperCol: { span: 16 },
		};
		const tailLayout = {
			wrapperCol: { offset: 8, span: 16 },
		};
		const error = (err) => {
			message.error(err);
		};
		const onFinish = values => {
			Cognito.doVerify(
				userPool,
				values.verifyEmailInput,
				values.verifyCodeInput, function (err, msg) {
					if (err) error("error: " + JSON.stringify(err));
					else setVerifyInfo({
						verifyState: VerifyState.success,
						successString: "Verified email of new user " + JSON.stringify(msg)
					})
				})
		};

		const onFinishFailed = errorInfo => {
			console.log('Failed:', errorInfo);
		};
		return (
			<div className="height100Percent rowFlexBox alignItemsCenter justifyContentCenter">
				<Card 
				hoverable
				title={<Antd.Typography.Title level={4}>Verify</Antd.Typography.Title>}>
				<Form
					initialValues={{ remember: true }}
					onFinish={onFinish}
					onFinishFailed={onFinishFailed}
					className=""
				>
					<Form.Item >
						<span>You should receive a verification code in  your email.</span>
					</Form.Item>
					<Form.Item
						label=""
						name="verifyEmailInput"
						rules={[
							{ required: true, message: 'Please input your email!' },
							{ type: "email", message: 'Please input a valid email address!' }
						]}
					>
					<Input prefix={<MailOutlined  className="site-form-item-icon"/>} className="inputPadding" placeholder={'me@gmail.com'}/>
					</Form.Item>
					<Form.Item
						label=""
						name="verifyCodeInput"
						rules={[
							{ required: true, message: 'Please input your Verification Code!' },
							{ pattern: /\d{6}/, message: 'Check your email for six a digit number!' },

						]}
					>
					<Input prefix={<NumberOutlined  className="site-form-item-icon"/>} className="inputPadding" placeholder={'123456'}/>
					</Form.Item>
					<Form.Item >
						<Button type="primary" htmlType="submit">
							Submit
										              </Button>
					</Form.Item>
				</Form>
				</Card>
			</div>
		);
	}
	const { verifyState, username, email, password, confirmPassword } = verifyInfo
	return (
		<Common.DivWithClassName className='rowFlexBox justifyContentCenter alignItemsCenter LoginContainer height100Percent width100Percent'>

				{verifyState == VerifyState.success &&
					<Redirect to="/account/login" />
				}
				{verifyState == VerifyState.waitingToVerify &&
					getVerifyForm()
				}
		</Common.DivWithClassName>
	)
}
function Login(props) {
	const LoginState = {
		waitingToLogin: 1,
		success: 2,
		failure: 3
	}
	const [loginInfo, setLoginInfo] = useState({
		username: '',
		email: '',
		password: '',
		confirmPassword: '',
		loginState: LoginState.waitingToLogin,
		successString: '',
		errorString: ''
	});
	useEffect(() => {
		Cognito.doRefresh((err, msg) => {
			if (err) {
				console.error("error on do refresh", err)
				console.assert(false)
			}
			if (msg) {
				setLoginInfo({
					loginState: LoginState.success,
					successString: "User already logged in: " + JSON.stringify(msg)
				})
			}
		})
	})
	const onChange = e => {
		const { name, value } = e.target;
		setLoginInfo(loginInfo => loginInfo[name] = value)
	};
	const getLoginForm = () => {
		const layout = {
			labelCol: { span: 8 },
			wrapperCol: { span: 16 },
		};
		const tailLayout = {
			wrapperCol: { offset: 8, span: 16 },
		};
		const error = (err) => {
			message.error(err);
		};
		const onFinish = values => {
			Cognito.doLogin(
				userPool,
				values.loginEmailInput,
				values.loginPasswordInput, function (err, msg) {
					if (err) error("error: " + JSON.stringify(err));
					else setLoginInfo({
						loginState: LoginState.success,
						successString: "User successfully logged in: " + JSON.stringify(msg)
					})

				})
		};
		const onFinishFailed = errorInfo => {
			console.log('Failed:', errorInfo);
		};
		return (
			<Common.DivWithClassName className='rowFlexBox justifyContentCenter alignItemsCenter'>
			<Card 
			hoverable
			title={<Antd.Typography.Title level={4}>Login to Structure</Antd.Typography.Title>}>
				<Form
				style={{width:'600px'}}
					initialValues={{ remember: true }}
					onFinish={onFinish}
					onFinishFailed={onFinishFailed}
					className=""
				>
						<Form.Item>
							<Antd.Typography.Text type='secondary'>
								Be sure to join us on&nbsp;
					<a href="https://join.slack.com/t/structuresupport/shared_invite/zt-ddx04ho4-_q43i5o3zQ9jv00qx~dx8A" target="_blank">
									Slack.</a>
							</Antd.Typography.Text>
						</Form.Item>
					<Form.Item
						label=""
						name="loginEmailInput"
						rules={[
							{ required: true, message: 'Please input your email!' },
							{ type: "email", message: 'Please input a valid email address!' }
						]}
					>

						<Input prefix={<MailOutlined className="site-form-item-icon" />} className="inputPadding" placeholder={'me@gmail.com'} />
					</Form.Item>

					<Form.Item
						label=""
						name="loginPasswordInput"
						rules={[
							{ required: true, message: 'Please input your password!' }
						]}
					>
						<Input.Password prefix={<LockOutlined className="site-form-item-icon" />} className="inputPadding" placeholder="*****" />
					</Form.Item>
					<Form.Item style={{ marginTop: '-30px' }} >
						<a className="font3" href="/account/forgot">Forgot Password?</a>
					</Form.Item>


					<Form.Item>
						<Button type="primary"  htmlType="submit">Login to Structure</Button>
						<Antd.Divider orientation='left' plain>or</Antd.Divider>
						<Button onClick={Cognito.goGoogle}>Login With <GoogleOutlined/>Google</Button>
					</Form.Item>
				</Form>
			</Card>
</Common.DivWithClassName>
		);
	}
	const { loginState, username, email, password, confirmPassword } = loginInfo

	if (loginState == LoginState.success) {
		window.top.location.href = '/app/editor'
		return null;
	}
	return (
		<Row className='LoginContainer height100Percent' type="flex " justify="center" align="middle">
				{loginState == LoginState.success &&
					<Redirect to="/app/editor" />
				}
				{loginState == LoginState.waitingToLogin &&
					getLoginForm()
				}
		</Row>
	)
}


function Forgot() {
	const ForgotState = {
		waitingToForgot: 1,
		success: 2,
		failure: 3
	}


	const [forgotInfo, setForgotInfo] = useState({
		username: '',
		email: '',
		password: '',
		confirmPassword: '',
		forgotState: ForgotState.waitingToForgot,
		successString: '',
		errorString: ''
	});

	const onChange = e => {
		const { name, value } = e.target;
		setForgotInfo(forgotInfo => forgotInfo[name] = value)
	};
	const getForgotForm = () => {
		const layout = {
			labelCol: { span: 8 },
			wrapperCol: { span: 16 },
		};
		const tailLayout = {
			wrapperCol: { offset: 8, span: 16 },
		};
		const error = (err) => {
			message.error(err);
		};
		const onFinish = values => {
			Cognito.doForgot(
				userPool,
				values.forgotEmailInput, function (err, msg) {
					if (err) error("error: " + err.message);
					else setForgotInfo({
						forgotState: ForgotState.success,
						successString: "Successfully sent reset email: " + JSON.stringify(msg)
					})
				})
		};

		const onFinishFailed = errorInfo => {
			console.log('Failed:', errorInfo);
		};
		return (
				<Card hoverable title={<Antd.Typography.Title level={4}>Forgot Password?</Antd.Typography.Title>}>
					<Form
						style={{width:'600px'}}
						initialValues={{ remember: true }}
						onFinish={onFinish}
						onFinishFailed={onFinishFailed}
					>
						<Form.Item
							label="Email"
							name="forgotEmailInput"
							rules={[
								{ required: true, message: 'Please input your email!' },
								{ type: "email", message: 'Please input a valid email address!' }
							]}
						>
						<Input prefix={<MailOutlined className="site-form-item-icon" />} className="inputPadding" placeholder={'me@gmail.com'} />
						</Form.Item>
						<Form.Item>
							<Button type="primary" htmlType="submit">
								Submit
			</Button>
						</Form.Item>
					</Form>
				</Card>
		);
	}
	const { forgotState, username, email, password, confirmPassword } = forgotInfo
	return (
		<Common.DivWithClassName className='height100Percent width100Percent justifyContentCenter alignItemsCenter LoginContainer rowFlexBox'>
			{forgotState == ForgotState.success &&
				<Redirect to="/account/reset" />
			}
			{forgotState == ForgotState.waitingToForgot &&
				getForgotForm()
			}
		</Common.DivWithClassName>
	)
}

function Reset() {
	const ResetState = {
		waitingToReset: 1,
		success: 2,
		failure: 3
	}


	const [resetInfo, setResetInfo] = useState({
		username: '',
		email: '',
		password: '',
		confirmPassword: '',
		resetState: ResetState.waitingToReset,
		successString: '',
		errorString: ''
	});

	const onChange = e => {
		const { name, value } = e.target;
		setResetInfo(resetInfo => resetInfo[name] = value)
	};
	const getResetForm = () => {
		const layout = {
			labelCol: { span: 8 },
			wrapperCol: { span: 16 },
		};
		const tailLayout = {
			wrapperCol: { offset: 8, span: 16 },
		};
		const error = (err) => {
			message.error(err);
		};
		const onFinish = values => {
			Cognito.doReset(
				userPool,
				values.resetEmailInput,
				values.resetCodeInput,
				values.resetPasswordInput, function (err, msg) {
					if (err) error("error: " + err);
					else setResetInfo({
						resetState: ResetState.success,
						successString: "User successfully logged in: " + JSON.stringify(msg)
					})
				})
		};

		const onFinishFailed = errorInfo => {
			console.log('Failed:', errorInfo);
		};
		return (
			<div className="Form">
				<h2 style={{ textAlign: "center" }}>Reset Password</h2>

				<Form
					{...layout}
					name="basic"
					initialValues={{ remember: true }}
					onFinish={onFinish}
					onFinishFailed={onFinishFailed}
				>
					<Form.Item
						label="Email"
						name="resetEmailInput"
						rules={[
							{ required: true, message: 'Please input your email!' },
							{ type: "email", message: 'Please input a valid email address!' }
						]}
					>
						<Input />
					</Form.Item>

					<Form.Item
						label="Code"
						name="resetCodeInput"
						rules={[
							{ required: true, message: 'Please input your Reset Password Code!' },
							{ pattern: /\d{6}/, message: 'Check your email for six a digit number!' },

						]}
					>
						<Input />
					</Form.Item>

					<Form.Item
						label="Password"
						name="resetPasswordInput"
						rules={[
							{ required: true, message: 'Please input your password!' },
							{ min: 8, message: 'Minimum 8 Characters!' },
							{ pattern: /[0-9]/, message: 'At least one number is required!' },
							{ pattern: /[a-z]/, message: 'At least one lowercase character required!' },
							{ pattern: /[A-Z]/, message: 'At least one uppercase character required!' },
							{ pattern: /[!@#$%^&*()\\|\<>\/?,.~`;'"\[\]\{\}]/, message: 'At least one special character required!' }
						]}
					>
						<Input.Password />
					</Form.Item>



					<Form.Item {...tailLayout}>
						<Button type="primary" htmlType="submit">
							Submit
			</Button>
					</Form.Item>
				</Form>
			</div>
		);
	}


	const { resetState, username, email, password, confirmPassword } = resetInfo
	return (
		<Row type="flex" justify="center" align="middle">
			<Col span={12} style={{ height: '400px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
				{resetState == ResetState.success &&
					<Redirect to="/account/login" />
				}
				{resetState == ResetState.waitingToReset &&
					getResetForm()
				}
			</Col>
		</Row>
	)
}

function Logout() {
	const LogoutState = {
		LoggedIn: 1,
		LoggedOut: 2
	}
	const [logoutInfo, setLogoutInfo] = useState({
		logoutState: LogoutState.LoggedIn
	});


	function handleLogout(e) {
		e.preventDefault();
		Cognito.doLogout((err, data) => {
			if (err) {
				console.log(err)
			} else {
				setLogoutInfo({ logoutState: LogoutState.LoggedOut });
			}
		})
	}
	const { logoutState } = logoutInfo
	return (
		<Row type="flex" justify="center" align="middle">
			<Col span={12} style={{ height: '400px', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
				{logoutState == LogoutState.LoggedIn &&

					<Button onClick={handleLogout}>Logout</Button>

				}
				{logoutState == LogoutState.LoggedOut &&
					<Redirect to="/account/login" />
				}
			</Col>
		</Row>
	)
}


function Home() {
	const HomeState = {
		ready: 1,
		loading: 2
	}
	const [homeInfo, setHomeInfo] = useState({
		homeState: HomeState.ready,
		successString: '',
		errorString: ''
	});

	useEffect(() => {
		console.log('component mounted, maybe run refresh here');
	})

	function handleStart(e) {
		e.preventDefault();
		setHomeInfo({ homeState: HomeState.loading });
	}
	function handleKill(e) {
		e.preventDefault();
		setHomeInfo({ homeState: HomeState.ready });
	}
	const { homeState } = homeInfo
	return (
		<Row type="flex" justify="center" align="middle">
			<Col span={12} style={{ height: '400px', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
				{homeState == HomeState.ready &&
					<div>
						<Button onClick={(e) => { Cognito.doRefresh((err, data) => { console.log(data) }) }}>Run Refresh</Button><br />
						<Button onClick={(e) => { Cognito.doLogout((err, data) => { console.log(err + data) }) }}>Logout</Button><br />
						{/*<Button onClick={(e)=>{Dynamo.addClientJobDB({}, (err, data)=>{console.log(data)})}}>Run Add Client Job</Button><br />
			  <Button onClick={(e)=>{Dynamo.listClientJobDB((err, data)=>{console.log(data)})}}>Run List Client Jobs</Button><br />
			  <Button onClick={(e)=>{Dynamo.addClientStateDB({}, (err, data)=>{console.log(data)})}}>Run Add Client State</Button><br />
		  <Button onClick={(e)=>{Dyanomo.getClientStateDB((err, data)=>{console.log(data)})}}>Run Get Client State</Button>*/}

					</div>
				}
				{homeState == HomeState.loading &&
					<div>
						<Button onClick={handleKill}>Kill Job</Button>
					</div>
				}
			</Col>
		</Row>
	)
}
