import React, { useState, useEffect, useContext, useRef } from "react";
import { Paper, List } from '@mui/material';

import "./PersonList.css";
import { PersonColor } from './PersonColor';
import { MediaAgent, MediaControl } from "./MediaControl";

import { GlobalContext } from "./GlobalContext";

const PersonList = () => {
  const { ws, name } = useContext(GlobalContext);
  const [persons, setPersons] = useState<any>({});
  const [unselected, setUneslected] = useState([]);
  const [state, setState] = useState('lobby');
  const [color, setColor] = useState<string>('');
  const [peers, setPeers] = useState<any>({});

  const onWsMessage = (event: any) => {
    const data = JSON.parse(event.data);
    switch (data.type) {
    case 'game-update':
      console.log(`player-list - game update`, data.update);
     
      if ('unselected' in data.update) {
        setUneslected(data.update.unselected);
      }

      if ('persons' in data.update) {
        let found = false;
        for (let key in data.update.persons) {
          if (data.update.persons[key].name === name) {
            found = true;
            setColor(key);
            break;
          }
        }
        if (!found) {
          setColor('');
        }
        setPersons(data.update.persons);
      }
      
      if ('state' in data.update && data.update.state !== state) {
        setState(data.update.state);
      }
      break;
    default:
      break;
    }
  };
  const refWsMessage = useRef(onWsMessage);

  useEffect(() => { refWsMessage.current = onWsMessage; });

  useEffect(() => {
    if (!ws) {
      return;
    }
    const cbMessage = (e: any) => refWsMessage.current(e);
    ws.addEventListener('message', cbMessage);
    return () => {
      ws.removeEventListener('message', cbMessage);
    }
  }, [ws, refWsMessage]);

  useEffect(() => {
    if (!ws) {
      return;
    }
    ws.send(JSON.stringify({ 
      type: 'get', 
      fields: [ 'state', 'persons', 'unselected' ]
    }));
  }, [ws]);

  const toggleSelected = (key: string) => {
    if (!ws) {
      return;
    }
    ws.send(JSON.stringify({ 
      type: 'set', 
      field: 'color',
      value: color === key ? "" : key
    }));
  }

  const playerElements: any[] = [];

  const inLobby = state === 'lobby';
  const sortedPersons = [];

  for (let key in persons) {
    sortedPersons.push(persons[key]);
  }

  const sortPersons = (A: any, B: any) => {
    /* active player first */
    if (A.name === name) {
      return -1;
    }
    if (B.name === name) {
      return +1;
    }
    
    /* Sort active persons first */
    if (A.name && !B.name) {
      return -1;
    }
    if (B.name && !A.name) {
      return +1;
    }

    /* Ohterwise, sort by color */
    return A.color.localeCompare(B.color);
  };

  sortedPersons.sort(sortPersons);

  /* Array of just names... */
  unselected.sort((A: any, B: any) => {
    /* active player first */
    if (A === name) {
      return -1;
    }
    if (B === name) {
      return +1;
    }
    /* Then sort alphabetically */
    return A.localeCompare(B);
  });

  const videoClass = sortedPersons.length <= 2 ? 'Medium' : 'Small';
  
  sortedPersons.forEach(player => {
    const name = player.name;
    const selectable = inLobby && (player.status === 'Not active' || color === player.color);
    playerElements.push(
      <div
        data-selectable={selectable}
        data-selected={player.color === color}
        className="PersonEntry"
        onClick={() => { inLobby && selectable && toggleSelected(player.color) }} 
        key={`player-${player.color}`}>
        <div>
          <PersonColor color={player.color}/>
          <div className="Name">{name ? name : 'Available' }</div>
        { name && !player.live && <div className="NoNetwork"></div> }
        </div>
        { name && player.live && <MediaControl className={videoClass} peer={peers[name]} 
          isSelf={player.color === color}/> }
        { !name && <div></div> }
      </div>
    );
  });

  const waiting = unselected.map((player) => {
    return <div className={player === name ? 'Self' : ''} key={player}>
      <div>{ player }</div>
      <MediaControl className={'Small'} peer={peers[player]} isSelf={name === player}/>
    </div>
  });

  return (
    <Paper className={`PersonList ${videoClass}`}>
      <MediaAgent setPeers={setPeers}/>
      <List className="PersonSelector">
        { playerElements }
      </List>
      { unselected && unselected.length !== 0 && <div className="Unselected">
        <div>In lobby</div>
        <div>
          { waiting }
        </div>
      </div> }
    </Paper>
  );
}

export { PersonList };
