import React, { useState, useEffect, useRef, useContext } from 'react';
import { TokenContext } from '../utilities/token-provider';
import { io } from 'socket.io-client';

import '../../styles/popup-chat.css';

//TODO: I very much need to move this out of global state
const socket = io(`${process.env.CHAT_URI}/chat`);

const PopupChat = props => {
	const [open, setOpen] = useState(false);
	const [chatlog, setChatlog] = useState([{ emphasis: true, text: 'If chat doesn\'t load, reload the page' }]);

	const inputRef = useRef();
	const sendRef = useRef();
	const endRef = useRef();

	const authTokens = useContext(TokenContext);

	const pushChatlog = line => setChatlog(prevChatlog => [...prevChatlog, line]);

	useEffect(() => {
		socket.on('message', message => pushChatlog(message));
		socket.on('backlog', messages => setChatlog(prev => [...prev, ...messages]));
		socket.on('disconnect', reason => pushChatlog({ emphasis: true, text: 'Lost connection' }));
	}, []);

	useEffect(() => {
		if (open) {
			endRef.current.scrollIntoView();
		}
	}, [chatlog, open]);

	if (!open) {
		return (
			<div className='chat'>
				<button type='button' className='open' onClick={() => authTokens.tokenCallback(accessToken => handleOpen(setOpen, accessToken))}>Open Chat</button>
			</div>
		);
	}

	return (
		<div className='chat'>
			<div className='log'>
				<ul className='scrollable'>
					{chatlog.map((line, index) => processLine(line, index, authTokens.accessToken))}
					<li ref={endRef} />
				</ul>
			</div>
			<input type='text' className='input' placeholder='message' onKeyPress={evt => evt.key == 'Enter' ? sendRef.current.click() : ''} ref={inputRef} />
			<button type='button' className='send' onClick={() => authTokens.tokenCallback(accessToken => handleSend(inputRef, pushChatlog, authTokens.getPayload().username, accessToken))} ref={sendRef}>Send</button>
			<button type='button' className='close' onClick={() => handleClose(setOpen)}>Close Chat</button>
		</div>
	);
};

//handlers
const handleOpen = (setOpen, accessToken) => {
	setOpen(true);

	socket.emit('open chat', {
		accessToken
	});
};

const handleClose = setOpen => {
	setOpen(false);
};

const handleSend = (inputRef, pushChatlog, username, accessToken) => {
	if (inputRef.current.value == '') {
		return;
	}

	socket.emit('message', {
		accessToken,
		text: inputRef.current.value
	});

	if (!inputRef.current.value.startsWith('/')) {
		pushChatlog({ username: username, text: inputRef.current.value });
	}

	inputRef.current.value = '';
};

//render each line
const processLine = (line, index, accessToken) => {
	let content = <div className='content'>{line.username ? <span className='username'>{line.username}: </span> : ''}{line.text ? <span className='text'>{line.text}</span> : ''}</div>;

	//decorators
	if (line.emphasis) {
		content = <em>{content}</em>;
	}

	if (line.strong) {
		content = <strong>{content}</strong>;
	}

	return <li key={index} className='line'>{content}<a className='report' onClick={() => processReport(line, accessToken)}>!!!</a></li>;
};

const processReport = (line, accessToken) => {
	const yes = confirm('Report this message?');

	if (yes) {
		socket.emit('report', {
			accessToken,
			index: line.index
		});
	}
};

export default PopupChat;