import Icon from '@mdi/react';
import axios from 'axios';
import { ReactNode, useContext, useEffect, useState } from 'react';

import { userGames, userInfo } from '../api/api';
import { AccountAvatar } from '../components/account';
import { DialogBox } from '../components/dialogBox';
import { Footer } from '../components/footer';
import { NavBar } from '../components/navbar';
import { CenteredPage, PageTitle } from '../components/page';
import RecentGames from '../components/recentGames';
import { SocketContext } from '../components/socketContext';
import { ToastContext } from '../components/toast';
import { Button, IconLabelButton, Vierkant } from '../components/ui';

import ArrowDownwardOutlinedIcon from '@material-ui/icons/ArrowDownwardOutlined';
import ArrowUpwardOutlinedIcon from '@material-ui/icons/ArrowUpwardOutlined';
import AssignmentIndOutlinedIcon from '@material-ui/icons/AssignmentIndOutlined';
import DoneOutlinedIcon from '@material-ui/icons/DoneOutlined';
import EditOutlinedIcon from '@material-ui/icons/EditOutlined';
import PeopleOutlineOutlinedIcon from '@material-ui/icons/PeopleOutlineOutlined';
import PersonAddOutlinedIcon from '@material-ui/icons/PersonAddOutlined';
import SettingsOutlinedIcon from '@material-ui/icons/SettingsOutlined';
import {
	mdiAccountCancelOutline,
	mdiAccountMinusOutline,
	mdiAccountRemoveOutline,
	mdiCheckboxBlankCircle,
	mdiClipboardTextOutline,
	mdiEarth,
	mdiEqual,
	mdiGamepadSquareOutline,
} from '@mdi/js';

function InfoModule(props: {
	label: string;
	icon: ReactNode;
}) {
	return <div className='infoModule posrel'>
		<div className='iconWrapper posabs'>
			{props.icon}
		</div>
		<div className='labelWrapper posabs h0 b0'>
			<span className='label posabs center fullwidth'>
				{props.label}
			</span>
		</div>
	</div>;
}

export default function AccountPage() {
	var server = typeof window === 'undefined';
	var loggedIn = !server && document.cookie.includes('token');
	var pageID = server ? '' : new URLSearchParams(window.location.search).get('id');

	if (!loggedIn && !pageID) !server && window.history.go(-1);
	var reqData = loggedIn && pageID ? { 'id': pageID } : undefined;

	var [user, setUser] = useState<userInfo>();
	var [gameInfo, setGameInfo] = useState<userGames>();
	var [editingStatus, setEditingStatus] = useState(false);
	var [relation, setRelation] = useState<userInfo['relation']>('none');
	var [ownPage, setOwnPage] = useState(loggedIn && !pageID);

	var { toast } = useContext(ToastContext);
	var { io } = useContext(SocketContext);

	async function getUserData(): Promise<userInfo> {
		try {
			var userReq = await axios.request<userInfo>({
				method: 'post',
				url: `/api/user/info`,
				headers: { 'content-type': 'application/json' },
				data: reqData,
			});
			setUser(userReq.data);
			return userReq.data;
		} catch (err) {
			toast({ message: 'error', type: 'error', description: err.toString() });
		}
	}

	async function getRelationTo(user: userInfo) {
		var user = await getUserData();
		if (!user) return;
		setRelation(user.relation || 'none');
	}

	function setIOListeners(user: userInfo) {
		io.on('changedRelation', (data: { id: string; }) => {
			if (data.id != user.id) return;
			getRelationTo(user);
		});
		io.on('incomingFriendRequest', getRelationTo);
	}

	useEffect(() => {
		(async () => {
			var user = await getUserData();

			getRelationTo(user);
			setIOListeners(user);
		})();
	}, []);

	useEffect(() => {
		axios.request<userInfo>({
			method: 'post',
			url: `/api/user/info`,
			headers: { 'content-type': 'application/json' },
		})
			.then(response => {
				setOwnPage(ownPage || response.data.id == pageID);
			})
			.catch(err => {
				toast({ message: 'error', type: 'error', description: err.toString() });
			});
	}, []);

	// Get recent games
	useEffect(() => {
		axios.request<userGames>({
			method: 'post',
			url: `/api/user/games`,
			headers: { 'content-type': 'application/json' },
			data: reqData,
		})
			.then(response => {
				setGameInfo(response.data);
			})
			.catch(err => {
				toast({ message: 'error', type: 'error', description: err.toString() });
			});
	}, []);

	return <div>
		<NavBar />
		<CenteredPage width={802}>
			<PageTitle>Profiel</PageTitle>
			<div>
				{!loggedIn && <DialogBox title='Maak een account aan' onclick={() => window.location.href = '/'}>
					<p className='center'>
						Om de accounts van andere gebruikers te zien moet je inloggen of een account aanmaken
					</p>
					<div className='pad-s'></div>
					<div className='sidebyside fullwidth'>
						<Button href='/register' text='Registreren' className='register w1fr' />
						<Button href='/login' text='Inloggen' className='login w1fr' />
					</div>
				</DialogBox>}
			</div>
			<Vierkant className='accountHeader w100m2m pad-l bg-800'>
				<div className='inner posrel'>
					<AccountAvatar size={128} id={user?.id || ''} />
					<div className='userInfo dispinbl valigntop'>
						<h2 className='username'>{user?.username}</h2>
						<p
							id='status'
							className='status round-t'
							contentEditable={editingStatus ? 'true' : 'false'}
							suppressContentEditableWarning={true}
						>
							{user?.status}
						</p>
					</div>
					<div className='posabs b0 r0'>
						{loggedIn && <div>
							{ownPage
								? <div>
									<IconLabelButton
										icon={<SettingsOutlinedIcon />}
										href='/settings'
										text='Instellingen'
									/>
									{!editingStatus
										? <IconLabelButton
											icon={<EditOutlinedIcon />}
											text='Status bewerken'
											onclick={() => setEditingStatus(true)}
										/>
										: <IconLabelButton
											icon={<DoneOutlinedIcon />}
											text='Status opslaan'
											onclick={() => {
												setEditingStatus(false);
												axios.request({
													method: 'post',
													url: `/api/user/status`,
													headers: { 'content-type': 'application/json' },
													data: { 'status': document.getElementById('status').innerText },
												});
											}}
										/>}
								</div>
								: <div>
									{(() => {
										var icon = {
											'blocked': <Icon size={1} path={mdiAccountCancelOutline} />,
										}[relation] || <Icon size={1} path={mdiAccountCancelOutline} />;

										var text = {
											'blocked': 'Deblokkeren',
										}[relation] || 'Blokkeren';

										return <IconLabelButton
											icon={icon}
											text={text}
											onclick={() => {
												var nextRelation = {
													'blocked': {
														'endpoint': '/api/social/unblock',
														'action': `${user.username} gedeblokkeerd`,
														'relation': 'none',
														'icon': <Icon size={1} path={mdiAccountCancelOutline} />,
													},
												}[relation] || {
													'endpoint': '/api/social/block',
													'action': `${user.username} geblokkeerd`,
													'relation': 'blocked',
													'icon': <Icon size={1} path={mdiAccountCancelOutline} />,
												};

												axios.request({
													method: 'post',
													url: nextRelation.endpoint,
													headers: { 'content-type': 'application/json' },
													data: { 'id': user?.id },
												})
													.then(() => {
														toast({
															message: nextRelation.action,
															type: 'confirmation',
															icon: nextRelation.icon,
														});
														setRelation(nextRelation.relation);
													});
											}}
										/>;
									})()}
									{(() => {
										var icon = {
											'friends': <Icon size={1} path={mdiAccountMinusOutline} />,
											'outgoing': <Icon size={1} path={mdiAccountRemoveOutline} />,
											'incoming': <PersonAddOutlinedIcon />,
										}[relation] || <PersonAddOutlinedIcon />;

										var text = {
											'friends': 'Vriend verwijderen',
											'outgoing': 'Vriendschapsverzoek annuleren',
											'incoming': 'Vriendschapsverzoek accepteren',
										}[relation] || 'Vriendschapsverzoek sturen';

										return <IconLabelButton
											icon={icon}
											text={text}
											onclick={() => {
												var nextRelation = {
													'friends': {
														'endpoint': '/api/social/remove',
														'action': `${user.username} succesvol verwijderd als vriend`,
														'relation': 'none',
														'icon': <Icon size={1} path={mdiAccountMinusOutline} />,
													},
													'outgoing': {
														'endpoint': '/api/social/remove',
														'action':
															`Vriendschapsverzoek naar ${user.username} geannuleerd`,
														'relation': 'none',
														'icon': <Icon size={1} path={mdiAccountMinusOutline} />,
													},
													'incoming': {
														'endpoint': '/api/social/accept',
														'action':
															`Vriendschapsverzoek van ${user.username} geaccepteerd`,
														'relation': 'friends',
														'icon': <PersonAddOutlinedIcon />,
													},
												}[relation] || {
													'endpoint': '/api/social/request',
													'action': `Vriendschapsverzoek gestuurd naar ${user.username}`,
													'relation': 'outgoing',
													'icon': <PersonAddOutlinedIcon />,
												};

												axios.request({
													method: 'post',
													url: nextRelation.endpoint,
													headers: { 'content-type': 'application/json' },
													data: { 'id': user?.id },
												})
													.then(() => {
														toast({
															message: nextRelation.action,
															type: 'confirmation',
															icon: nextRelation.icon,
														});
														setRelation(nextRelation.relation);
													});
											}}
										/>;
									})()}
								</div>}
						</div>}
					</div>
				</div>
			</Vierkant>
			<Vierkant className='infosection pad-l w100m2m bg-800'>
				<div className='inner sidebyside'>
					<InfoModule
						icon={<Icon size={1} path={mdiCheckboxBlankCircle} className='outcome win' />}
						label='Online'
					/>
					<InfoModule
						icon={<AssignmentIndOutlinedIcon />}
						label={(() => {
							var memberSince = 'Lid sinds';

							var registered = new Date(user?.registered);
							memberSince += ' ' + registered.toLocaleString('nl-nl', { month: 'long', day: 'numeric' });

							var currentYear = new Date().getFullYear();
							var memberYear = registered.getFullYear();
							if (currentYear != memberYear) memberSince += ' ' + memberYear;

							return memberSince;
						})()}
					/>
					<InfoModule
						icon={<PeopleOutlineOutlinedIcon />}
						label={(() => {
							var label = user?.friends.toString() + ' ';
							label += user?.friends == 1 ? 'vriend' : 'vrienden';
							return label;
						})()}
					/>
					<InfoModule icon={<Icon size={1} path={mdiEarth} />} label='Nederland' />
				</div>
			</Vierkant>
			<Vierkant className='infosection pad-l w100m2m sidebyside bg-800'>
				<div className='inner sidebyside'>
					<InfoModule
						icon={<ArrowUpwardOutlinedIcon className='outcome win' />}
						label={gameInfo?.totals.win + ' keer gewonnen'}
					/>
					<InfoModule
						icon={<Icon size={1} path={mdiEqual} className='subtile' />}
						label={gameInfo?.totals.draw + ' keer gelijkspel'}
					/>
					<InfoModule
						icon={<ArrowDownwardOutlinedIcon className='outcome lose' />}
						label={gameInfo?.totals.lose + ' keer verloren'}
					/>
					<InfoModule
						icon={<Icon size={1} path={mdiClipboardTextOutline} />}
						label={'Score: ' + user?.rating}
					/>
					<InfoModule
						icon={<Icon size={1} path={mdiGamepadSquareOutline} />}
						label={(() => {
							var label = gameInfo?.totals.games.toString() + ' ';
							label += gameInfo?.totals.games == 1 ? 'potje' : 'potjes';
							return label;
						})()}
					/>
				</div>
			</Vierkant>
			<Vierkant className='pad-l bg-800'>
				<RecentGames games={gameInfo?.games} />
			</Vierkant>
		</CenteredPage>
		<Footer />
	</div>;
}