import React, { useState, useEffect } from "react";
import "./Table.css";
import history from "./history.js";
import Paper from '@material-ui/core/Paper';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import { makeStyles } from '@material-ui/core/styles';
import { orange,lightBlue, red, grey } from '@material-ui/core/colors';
import Avatar from '@material-ui/core/Avatar';
import Moment from 'react-moment';
import Board from './Board.js'

//import moment from 'moment';

/* Start of withRouter polyfill */
// https://reactrouter.com/docs/en/v6/faq#what-happened-to-withrouter-i-need-it
import {
  useLocation,
  useNavigate,
  useParams
} from "react-router-dom";

function withRouter(Component) {
  function ComponentWithRouterProp(props) {
    let location = useLocation();
    let navigate = useNavigate();
    let params = useParams();
    return (
      <Component
        {...props}
        router={{ location, navigate, params }}
      />
    );
  }

  return ComponentWithRouterProp;
}
/* end of withRouter polyfill */

const base = process.env.PUBLIC_URL;
   
const assetsPath = `${base}/assets`;
const gamesPath = `${base}/games`;

const useStyles = makeStyles((theme) => ({
  root: {
    display: 'flex',
    '& > *': {
      margin: theme.spacing(1),
    },
  },
  R: {
    color: theme.palette.getContrastText(red[500]),
    backgroundColor: red[500],
  },
  O: {
    color: theme.palette.getContrastText(orange[500]),
    backgroundColor: orange[500],
  },
  W: {
    color: theme.palette.getContrastText(grey[500]),
    backgroundColor: grey[500],
  },
  B: {
    color: theme.palette.getContrastText(lightBlue[500]),
    backgroundColor: lightBlue[500],
  },
}));

const Dice = ({ pips }) => {
  let name;
  switch (pips.toString()) {
  case '1': name = 'one'; break;
  case '2': name = 'two'; break;
  case '3': name = 'three'; break;
  case '4': name = 'four'; break;
  case '5': name = 'five'; break;
  default:
  case '6': name = 'six'; break;
  }
  return (
    <img alt={name} className="Dice" src={`${assetsPath}/dice-six-faces-${name}.svg`}/>
  );
}

const PlayerColor = ({ color }) => {
  const classes = useStyles();
  return (
    <Avatar className={['PlayerColor', classes[color]].join(' ')}/>
  );
};
  
const Placard = ({type}) => {
  return (
    <div className="Placard"
      style={{
        backgroundImage:`url(${assetsPath}/gfx/placard-${type}.png)`
      }}
    />
  );
};

class Development extends React.Component {
  render() {
    const array = [];
    for (let i = 0; i < this.props.count; i++) {
      if (this.props.type.match(/-$/)) {
        array.push(i + 1);//Math.ceil(Math.random() * this.props.max));
      } else {
        array.push("");
      }
    }
    return (
      <div className="Stack">
        { React.Children.map(array, i => (
          <div className="Development"
            style={{backgroundImage:`url(${assetsPath}/gfx/card-${this.props.type}${i}.png)`}}>
          </div>
        )) }
      </div>
    );
  }
};

const Resource = ({ type, count }) => {
  const array = new Array(Number(count ? count : 0));
  const select = (event) => {
    event.target.classList.toggle('Selected');
  };
  return (
    <>
    { array.length > 0 && 
      <div className="Stack">
      { React.Children.map(array, i => (
        <div className="Resource"
          data-type={type}
          onClick={select}
          style={{backgroundImage:`url(${assetsPath}/gfx/card-${type}.png)`}}>
        </div>
      )) }
    </div>
    }
    </>
  );
};

const Chat = ({ table }) => {
  const [lastTop, setLastTop] = useState(0),
    [autoScroll, setAutoscroll] = useState(true),
    [scrollTime, setScrollTime] = useState(0);
 
  const chatInput = (event) => {
  };

  const chatKeyPress = (event) => {
    if (event.key === "Enter") {
      if (!autoScroll) {
        setAutoscroll(true);
      }

      table.sendChat(event.target.value);
      
      event.target.value = "";
    }
  };

  const chatScroll = (event) => {
    const chatList = event.target,
      fromBottom = Math.round(Math.abs((chatList.scrollHeight - chatList.offsetHeight) - chatList.scrollTop));

    /* If scroll is within 20 pixels of the bottom, turn on auto-scroll */
    const shouldAutoscroll = (fromBottom < 20);

    if (shouldAutoscroll !== autoScroll) {
      setAutoscroll(shouldAutoscroll);
    }

    /* If the list should not auto scroll, then cache the current
     * top of the list and record when we did this so we honor
     * the auto-scroll for at least 500ms */
    if (!shouldAutoscroll) {
      const target = Math.round(chatList.scrollTop);
      if (target !== lastTop) {
        setLastTop(target);
        setScrollTime(Date.now());
      }
    }
  };

  useEffect(() => {
    const chatList = document.getElementById("ChatList"),
      currentTop = Math.round(chatList.scrollTop);

    if (autoScroll) {
      /* Auto-scroll to the bottom of the chat window */
      const target = Math.round(chatList.scrollHeight - chatList.offsetHeight);
      if (currentTop !== target) {
        chatList.scrollTop = target;
      }
      return;
    }

    /* Maintain current position in scrolled view if the user hasn't
     * been scrolling in the past 0.5s */
    if ((Date.now() - scrollTime) > 500 && currentTop !== lastTop) {
      chatList.scrollTop = lastTop;
    }
  });
  
  //const timeDelta = game.timestamp - Date.now();
  if (!table.game) {
    console.log("Why no game?");
  }

  const messages = table.game && table.game.chat.map((item, index) => {
    /* If the date is in the future, set it to now */
    const name = item.from ? item.from : item.color,
      from = name ? `${name}, ` : '';
    let message;
    const dice = item.message.match(/^(.*rolled )([1-6])(, ([1-6]))?(.*)$/);
    if (dice) {
      if (dice[4]) {
        message = <>{dice[1]}<Dice pips={dice[2]}/>, <Dice pips={dice[4]}/>{dice[5]}</>;
      } else {
        message = <>{dice[1]}<Dice pips={dice[2]}/>{dice[5]}</>;
      }
    } else {
      message = item.message;
    }
    return (
      <ListItem key={`msg-${item.date}`}>
        <PlayerColor color={item.color}/>
        <ListItemText primary={message}
          secondary={(<>{from}
            <Moment fromNow date={item.date > Date.now() ?
              Date.now() : item.date} interval={1000}/></>)} />
      </ListItem>
    );
  });

  const name = table.game ? table.game.name : "Why no game?";

  return (
    <Paper className="Chat">
      <List className="ChatList" id="ChatList" onScroll={chatScroll}>
        { messages }
      </List>
      <TextField className="ChatInput"
        disabled={!name}
        onChange={chatInput}
        onKeyPress={chatKeyPress}
        label={(<Moment format="h:mm:ss" interval={1000}/>)} variant="outlined"/>
    </Paper>
  );
}

const StartButton = ({ table }) => {
  const startClick = (event) => {
    table.setGameState("game-order").then((state) => {
      table.game.state = state;
    });
  };

  return (
    <Button disabled={!table.game.color || table.game.active < 2} onClick={startClick}>Start game</Button>
  );
};

const WaitingForPlayer = ({table}) => {
  return (
    <div className="WaitingForPlayer">
      { table.game && table.game.turn && <Paper>
        <div className="Title">Waiting for {table.game.turn.name} to complete their turn.</div>
      </Paper> }
    </div>
  );
}

const GameOrder = ({table}) => {

  const rollClick = (event) => {
    table.throwDice();
  }

  if (!table.game) {
    return (<></>);
  }

  let players = [], hasRolled = true;
  for (let color in table.game.players) {
    const item = table.game.players[color],
      name = getPlayerName(table.game.sessions, color);
    if (color === table.game.color) {
      hasRolled = item.orderRoll !== 0;
    }
    if (name) {
      if (!item.orderRoll) {
        item.orderRoll = 0;
      }
      players.push({ name: name, color: color, ...item });
    }
  }

  players.sort((A, B) => {
    if (A.order === B.order) {
      if (A.orderRoll === B.orderRoll) {
        return A.name.localeCompare(B.name);
      }    
      return B.orderRoll - A.orderRoll;
    }
    return B.order - A.order;
  });

  players = players.map(item => 
    <div className="GameOrderPlayer" key={`player-${item.color}`}>
      <PlayerColor color={item.color}/>
      <div>{item.name}</div>
      { item.orderRoll !== 0 && <>rolled <Dice pips={item.orderRoll}/>.</> }
      { item.orderRoll === 0 && <>has not rolled yet. {item.orderStatus}</>}
    </div>
  );

  return (
    <div className="GameOrder">
      { table.game && <Paper>
        <div className="Title">Game Order</div>
        <div className="PlayerList">
          { players }
        </div>
        <Button disabled={hasRolled} onClick={rollClick}>Roll Dice</Button>
      </Paper> }
    </div>
  );
};

const SelectPlayer = ({table, players}) => {
  const playerClick = (event) => {
    table.stealResource(event.currentTarget.getAttribute('data-color'));
  }

  if (!table.game) {
    return (<></>);
  }

  let list = players.map(color => {
    let item = {
      color: color,
      name: getPlayerName(table.game.sessions, color)
    };
    return <div className="SelectPlayerItem" 
      onClick={playerClick}
      data-color={color}
      key={`player-${item.color}`}>
      <PlayerColor color={item.color}/>
      <div>{item.name}</div>
    </div>;
  });

  return (
    <div className="SelectPlayer">
      { table.game && <Paper>
        <div className="Title">Select Player to Steal From</div>
        <div className="SelectPlayerList">
          { list }
        </div>
      </Paper> }
    </div>
  );
};

const Action = ({ table }) => {
  const discardClick = (event) => {
    const nodes = document.querySelectorAll('.Hand .Selected'),
      discarding = { wheat: 0, brick: 0, sheep: 0, stone: 0, wood: 0 };
    for (let i = 0; i < nodes.length; i++) {
      discarding[nodes[i].getAttribute("data-type")]++;
      nodes[i].classList.remove('Selected');
    }
    return table.discard(discarding);
  }

  const newTableClick = (event) => {
    return table.shuffleTable();
  };

  const rollClick = (event) => {
    table.throwDice();
  }

  const passClick = (event) => {
    return table.passTurn();
  }

  const quitClick = (event) => {
    table.setSelected("");
  }

  if (!table.game) {
    console.log("Why no game?");
    return (<Paper className="Action"/>);
  }

  const inLobby = table.game.state === 'lobby',
    player = table.game ? table.game.player : undefined;

  return (
    <Paper className="Action">
      {  inLobby && <>
        <StartButton table={table}/>
        <Button disabled={!table.game.color} onClick={newTableClick}>New table</Button>
        <Button disabled={table.game.color ? true : false} onClick={() => {table.setState({ pickName: true})}}>Change name</Button>    </> }
      { table.game.state === 'normal' && <>
        <Button disabled={(table.game.turn.color !== table.game.color || table.game.turn.roll) ? true : false} onClick={rollClick}>Roll Dice</Button>
        <Button disabled>Trade</Button>
        <Button disabled>Build</Button>
        { table.game.turn.roll === 7 && player && player.mustDiscard > 0 &&
          <Button onClick={discardClick}>Discard</Button>
        }
        <Button disabled={(table.game.turn.color !== table.game.color || !table.game.turn.roll) ? true : false} onClick={passClick}>Done</Button>
      </> }
      { !inLobby &&
        <Button onClick={quitClick}>Quit</Button>
      }
    </Paper>
  );
}

const PlayerName = ({table}) => {
  const [name, setName] = useState((table && table.game && table.game.name) ? table.game.name : "");

  const nameChange = (event) => {
    setName(event.target.value);
  }

  const sendName = () => {
    if (name !== table.game.name) {
      table.setPlayerName(name);
    } else {
      table.setState({ pickName: false, error: "" });
    }
  }

  const nameKeyPress = (event) => {
    if (event.key === "Enter") {
      sendName();
    }
  }

  return (
    <Paper className="PlayerName">
      <TextField className="nameInput"
        onChange={nameChange}
        onKeyPress={nameKeyPress}
        label="Enter your name"
        variant="outlined"
        value={name}
        />
        <Button onClick={() => sendName()}>Set</Button>
    </Paper>
  );
};

const getPlayerName = (sessions, color) => {
  for (let i = 0; i < sessions.length; i++) {
    const session = sessions[i];
    if (session.color === color) {
      return session.name;
    }
  }
  return null;
}

/* This needs to take in a mechanism to declare the
 * player's active item in the game */
const Players = ({ table }) => {
  const toggleSelected = (key) => {
    table.setSelected(table.game.color === key ? "" : key);
  }

  const players = [];

  if (!table.game) {
    return (<></>);
  }
  for (let color in table.game.players) {
    const item = table.game.players[color], inLobby = table.game.state === 'lobby';
    if (!inLobby && item.status === 'Not active') {
      continue;
    }
    const name = getPlayerName(table.game.sessions, color),
      selectable = table.game.state === 'lobby' && (item.status === 'Not active' || table.game.color === color);
    let toggleText = name ? name : "Available";
    players.push((
      <div
        data-selectable={selectable}
        data-selected={table.game.color === color}
        className="PlayerEntry"
        onClick={() => { inLobby && selectable && toggleSelected(color) }} 
        key={`player-${color}`}>
        <PlayerColor color={color}/>
        <ListItemText primary={toggleText} secondary={(
        <>
          { item.status + ' ' }
          { item.status !== 'Not active' && <Moment fromNow date={item.lastActive > Date.now() ? Date.now() : item.lastActive}/>}
        </>)} />
      </div>
    ));
  }

  return (
    <Paper className="Players">
      <List className="PlayerSelector">
        { players }
      </List>
    </Paper>
  );
}

console.log("TODO: Convert this to a function component!!!!");

class Table extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      total: 0,
      wood: 0,
      sheep: 0,
      brick: 0,
      stone: 0,
      wheat: 0,
      game: null,
      message: "",
      error: "",
      signature: ""
    };
    this.componentDidMount = this.componentDidMount.bind(this);
    this.updateDimensions = this.updateDimensions.bind(this);
    this.throwDice = this.throwDice.bind(this);
    this.resetGameLoad = this.resetGameLoad.bind(this);
    this.loadGame = this.loadGame.bind(this);
    this.rollDice = this.rollDice.bind(this);
    this.setGameState = this.setGameState.bind(this);
    this.shuffleTable = this.shuffleTable.bind(this);
    this.discard = this.discard.bind(this);
    this.passTurn = this.passTurn.bind(this);
    this.updateGame = this.updateGame.bind(this);
    this.setPlayerName = this.setPlayerName.bind(this);
    this.setSelected = this.setSelected.bind(this);
    this.updateMessage = this.updateMessage.bind(this);
    this.gameSignature = this.gameSignature.bind(this);
    this.sendAction = this.sendAction.bind(this);
    
    this.mouse = { x: 0, y: 0 };
    this.radius = 0.317;

    this.loadTimer = null;

    this.game = null;
    this.pips = [];
    this.tiles = [];
    this.borders = [];
    this.tabletop = null;
    this.closest = {
      info: {},
      tile: null,
      road: null,
      tradeToken: null,
      settlement: null
    };

    this.id = (props.router && props.router.params.id) ? props.router.params.id : 0;
  }

  sendAction(action, value, extra) {
    if (this.loadTimer) {
      window.clearTimeout(this.loadTimer);
      this.loadTimer = null;
    }

    return window.fetch(`${base}/api/v1/games/${this.state.game.id}/${action}/${value ? value : ''}`, {
      method: "PUT",
      cache: 'no-cache',
      credentials: 'same-origin',
      headers: {
        'Content-Type': 'application/json'
      },
      body: extra ? JSON.stringify(extra) : undefined
    }).then((res) => {
      if (res.status >= 400) {
        throw new Error(`Unable to perform ${action}!`);
      }
      return res.json();
    }).then((game) => {
      const error = (game.status !== 'success') ? game.status : undefined;
      this.updateGame(game);
      this.updateMessage();
      this.setState({ error: error });
    }).catch((error) => {
      console.error(error);
      this.setState({error: error.message});
    }).then(() => {
      this.resetGameLoad();
    });
  }

  setSelected(key) {
    return this.sendAction('player-selected', key);
  }

  sendChat(message) {
    return this.sendAction('chat', undefined, {message: message});
  }


  setPlayerName(name) {
    return this.sendAction('player-name', name)
    .then(() => {
      this.setState({ pickName: false });
    });
  }  

  shuffleTable() {
    return this.sendAction('shuffle')
    .then(() => {
      this.setState({ error: "Table shuffled!" });
    });
  }

  discard(resources) {
    return this.sendAction('discard', undefined, resources);
  }

  passTurn() {
    return this.sendAction('pass');
  };

  rollDice() {
    return this.sendAction('roll');
  }

  loadGame() {
    if (this.loadTimer) {
      window.clearTimeout(this.loadTimer);
      this.loadTimer = null;
    }

    if (!this.state.game) {
      console.error('Attempting to loadGame with no game set');
      return;
    }

    return window.fetch(`${base}/api/v1/games/${this.state.game.id}`, {
      method: "GET",
      cache: 'no-cache',
      credentials: 'same-origin',
      headers: {
        'Content-Type': 'application/json'
      }
    }).then((res) => {
      if (res.status >= 400) {
        console.log(res);
        throw new Error(`Server temporarily unreachable.`);
      }
      return res.json();
    }).then((game) => {
      const error = (game.status !== 'success') ? game.status : undefined;
      this.updateGame(game);
      this.updateMessage();
      this.setState({ error: error });
    }).catch((error) => {
      console.error(error);
      this.setState({error: error.message});
    }).then(() => {
      this.resetGameLoad();
    });
  }

  resetGameLoad() {
    if (this.loadTimer) {
      window.clearTimeout(this.loadTimer);
      this.loadTimer = 0;
    }
    this.loadTimer = window.setTimeout(this.loadGame, 1000);
  }
  
  setGameState(state) {
    if (this.loadTimer) {
      window.clearTimeout(this.loadTimer);
      this.loadTimer = null;
    }

    return window.fetch(`${base}/api/v1/games/${this.state.game.id}/state/${state}`, {
      method: "PUT",
      cache: 'no-cache',
      credentials: 'same-origin',
      headers: {
        'Content-Type': 'application/json'
      }
    }).then((res) => {
      if (res.status >= 400) {
        console.log(res);
        throw new Error(`Unable to set state to ${state}`);
      }
      return res.json();
    }).then((game) => {
      console.log (`Game state set to ${game.state}!`);
      this.updateGame(game);
      this.updateMessage();
    }).catch((error) => {
      console.error(error);
      this.setState({error: error.message});
    }).then(() => {
      this.resetGameLoad();
      return this.game.state;
    });
  }

  placeRobber(robber) {
    return this.sendAction('place-robber', robber);
  };

  placeSettlement(settlement) {
    return this.sendAction('place-settlement', settlement);
  }
  
  placeRoad(road) {
    return this.sendAction('place-road', road);
  }

  stealResource(color) {
    return this.sendAction('steal-resource', color);
  }

  throwDice() {
    return this.rollDice();

    if (0) {  
      if (this.game.state !== 'active') {
        return;
      }
      
      const sum = 0;//dice[0].pips + dice[1].pips;
      if (sum === 7) { /* Robber! */
        if (this.state.total > 7) {
          let half = Math.ceil(this.state.total * 0.5);
          this.setState({ total: this.state.total - half});
          while (half) {
            switch (Math.floor(Math.random() * 5)) {
            case 0: if (this.state.wood) { this.setState({ wood: this.state.wood - 1}); half--; } break;
            case 1: if (this.state.sheep) { this.setState({ sheep: this.state.sheep - 1}); half--; } break;
            case 2: if (this.state.stone) { this.setState({ stone: this.state.stone - 1}); half--; } break;
            case 3: if (this.state.brick) { this.setState({ brick: this.state.brick - 1}); half--; } break;
            case 4:
            default: if (this.state.wheat) { this.setState({ wheat: this.state.wheat - 1}); half--; } break;
            }
          }
        }
      } else {
        this.tiles.forEach((tile) => {
          if (tile.pip.roll !== sum) {
            return;
          }
          this.setState({ [tile.type]: this.state[tile.type] + 1});
          this.setState({ total: this.state.total + 1 });
        });
      }

      this.setState({
        total: this.state.total,
        wood: this.state.wood,
        sheep: this.state.sheep,
        stone: this.state.stone,
        brick: this.state.brick,
        wheat: this.state.wheat
      });
    }
  };

  updateDimensions() {
    const hasToolbar = false;

    if (this.updateSizeTimer) {
      clearTimeout(this.updateSizeTimer);
    }

    this.updateSizeTimer = setTimeout(() => {
      const container = document.getElementById("root"),
        offset = hasToolbar 
          ? container.firstChild.offsetHeight 
          : 0,
        height = window.innerHeight - offset;

      this.offsetY = offset;
      this.width = window.innerWidth;
      this.height = height;

      if (this.cards && this.cards.style) { 
        this.cards.style.top = `${offset}px`;
        this.cards.style.width = `${this.width}px`;
        this.cards.style.height = `${this.heigh}tpx`;
      }

      this.updateSizeTimer = 0;
    }, 250);
  }

  
  gameSignature(game) {
    if (!game) {
      return "";
    }
    const signature =
      game.borderOrder.map(border => Number(border).toString(16)).join('') + '-' +
      game.pipOrder.map(pip => Number(pip).toString(16)).join('') + '-' +
      game.tileOrder.map(tile => Number(tile).toString(16)).join('');

    return signature;
  };

  updateGame(game) {
    if (this.state.signature !== this.gameSignature(game)) {
      game.signature = this.gameSignature(game);
    }
//    console.log("Update Game", game);
    this.setState( { game: game });
    this.game = game;
  }

  updateMessage() {
    const player = (this.game && this.game.color) ? this.game.players[this.game.color] : undefined,
      name = this.game ? this.game.name : "";

    let message = <></>;
    if (this.state.pickName || !name) {
      message = <>{message}Enter the name you would like to be known by, then press&nbsp;<b>ENTER</b>&nbsp;or select &nbsp;<b>SET</b>.</>;
    } else {
      switch (this.game && this.game.state) {
      case 'lobby':
        message = <>{message}You are in the lobby as&nbsp;<b>{name}</b>.</>;
        if (!this.game.color) {
          message = <>{message}You need to pick your color.</>;
        } else {
          message = <>{message}You have selected <PlayerColor color={this.game.color}/>.</>;
        }
        message = <>{message}You can chat with other players below.</>;
        if (this.game.active < 2) {
          message = <>{message}Once there are two or more players, you can select <StartButton table={this}/>.</>;
        } else {
          message = <>{message}There are enough players to start the game. Select <StartButton table={this}/> when ready.</>;
        }
        break;
      case 'game-order':
        if (!player) {
          message = <>{message}This game as an observer as &nbsp;<b>{name}</b>.</>;
          message = <>{message}You can chat with other players below as&nbsp;<b>{this.game.name}</b>, but cannot play unless players go back to the Lobby.</>;
        } else {
          if (!player.order) {
            message = <>{message}You need to roll for game order. Click&nbsp;<b>Roll Dice</b>&nbsp;below.</>;
          } else {
            message = <>{message}You rolled <Dice pips={player.order}/> for game order. Waiting for all players to roll.</>;
            message = <>{message}<br/><b>THIS IS THE END OF THE FUNCTIONALITY SO FAR</b></>;
          }
        }
        break;
      case 'active':
        if (!player) {
          message = <>{message}This game is no longer in the lobby.<br/><b>TODO: Override game state to allow Lobby mode while in-game</b></>; 
        } else {
          message = <>{message}<br/><b>THIS IS THE END OF THE FUNCTIONALITY SO FAR</b></>;
        }
        break;
      case null:
      case undefined:
      case '':
        message = <>{message}The game is in a wonky state. Sorry :(</>;
        break;
      case 'normal':
        if (this.game && this.game.turn) {
          if (this.game.turn.roll === 7) {
            message = <>{message}Robber was rolled!</>;
            let move = true;
            for (let color in this.game.players) {
              let name = '';
              for (let i = 0; i < this.game.sessions.length; i++) {
                if (this.game.sessions[i].color === color) {
                  name = this.game.sessions[i].name;
                }
              }
              const discard = this.game.players[color].mustDiscard;
              if (discard) {
                move = false;
                message = <>{message}<PlayerColor color={color}/> {name} needs to discard {discard} resources.</>;
              }
            }
            if (move && (this.game.turn && !this.game.turn.placedRobber)) {
              message = <>{message}<PlayerColor color={this.game.turn.color}/> {this.game.turn.name} needs to move the robber.</>
            }
          }
        }
        break;
      default:
        message = <>{message}Game state is: {this.game.state}</>;
        break;
      }
    }
    this.setState({ message: message });
  }

  componentDidMount() {
    this.start = new Date();

     const params = {};
    if (this.id) {
      console.log(`Loading game: ${this.id}`);
      params.url = `${base}/api/v1/games/${this.id}`;
      params.method = "GET"
    } else {
      console.log("Requesting new game.");
      params.url = `${base}/api/v1/games/`;
      params.method = "POST";
    }

    window.fetch(params.url, {
      method: params.method,
      cache: 'no-cache',
      credentials: 'same-origin',
      headers: {
        'Content-Type': 'application/json'
      },
//      body: JSON.stringify(data) // body data type must match "Content-Type" header
    }).then((res) => {
      if (res.status < 400) {
        return res;
      }
      let error;
      if (!this.id) {
        error = `Unable to create new game.`;
        throw new Error(error);
      }

      error = `Unable to find game ${this.id}. Starting new game.`
      console.log(error);
      this.setState({ error: error });
    
      params.url = `${base}/api/v1/games/${this.id}`;
      params.method = "POST";
    
      return window.fetch(params.url, {
        method: params.method,
        cache: 'no-cache',
        credentials: 'same-origin',
        headers: {
          'Content-Type': 'application/json'
        }
      });
    }).then((res) => {
      return res.json();
    }).then((game) => {
//      console.log (`Game ${game.id} loaded ${moment().format()}.`);

      if (!this.id) {
        history.push(`${gamesPath}/${game.id}`);
      }

      this.updateGame(game);
      this.updateMessage();

      this.setState({ error: "" });
    }).catch((error) => {
      console.error(error);
      this.setState({error: error.message});
    }).then(() => {
      this.resetGameLoad();
    });

    setTimeout(this.updateDimensions, 1000);
  }

  componentWillUnmount() {
    if (this.loadTimer) {
      clearTimeout(this.loadTimer);
    }
    if (this.updateSizeTimer) {
      clearTimeout(this.updateSizeTimer);
      this.updateSizeTimer = 0;
    }
  }

  render() {
    const game = this.state.game,
      player = game ? game.player : undefined
    let color;
    switch (game ? game.color : undefined) {
    case "O": color = "orange"; break;
    case "R": color = "red"; break;
    case "B": color = "blue"; break;
    case "W": color = "white"; break;
    }
    return (
      <div className="Table">
        
        <div style={{display: "inline-flex", flex: 1, flexDirection: "column"}}>
          <Board table={this} game={game}/>
          { player !== undefined && 
            <div className="BottomBar">
              <div className="Hand">
                <Resource type="wood" count={player.wood}/>
                <Resource type="wheat" count={player.wheat}/>
                <Resource type="stone" count={player.stone}/>
                <Resource type="brick" count={player.brick}/>
                <Resource type="sheep" count={player.sheep}/>
              </div>
              <Placard type={`${color}`}/>
            </div>}
        </div>

        { game && <div className={'Game ' + game.state}>
          <Paper className="Message">{ this.state.message }</Paper>
          {(this.state.pickName || !game.name) && <PlayerName table={this}/> }
          {(!this.state.pickName && game.name) && <>
            <Players table={this}/>
            <Chat table={this}/>
            <Action table={this}/>
          </> }
        </div> }

        { game && game.state === 'game-order' &&
          <GameOrder table={this}/>
        }

        { game && game.state === 'normal' &&
          game.turn && 
          game.turn.color == game.color &&
          game.turn.actions && game.turn.actions.indexOf('steal-resource') !== -1 &&
          <SelectPlayer table={this} players={game.turn.limits.players}/>
        }

        { game && game.turn && game.turn.color !== game.color &&
          (game.state === 'initial-placement' || game.state === 'normal') &&
          (!game.player || !game.player.mustDiscard) && <WaitingForPlayer table={this}/>
        }

        { game && game.showCards && 
          <div className="Cards">
            { game && game.state === "active" && <>
              <div>In hand</div>
            
              <div>Available to play</div>
              <div className="Hand">
                <Development type="monopoly" count="1"/>
                <Development type="army-" max="14" count="4"/>
                <div className="Stack">
                  <Development type="vp-library" count="1"/>
                  <Development type="vp-market" count="1"/>
                </div>
              </div>
              <div>Points</div>
              <div className="Hand">
                <div className="Stack">
                  <Development type="vp-library" count="1"/>
                  <Development type="vp-palace" count="1"/>
                  <Development type="army-" max="14" count="6"/>
                </div>
              </div>
              <div className="Hand">
                <Placard type="largest-army"/>
                <Placard type="longest-road"/>
              </div>
            </> }
          </div>
        }

        { this.state.error && <Paper className="Error"><div>{this.state.error}</div></Paper> }

      </div>
    );
  }
}
export default withRouter(props => <Table {...props}/>);
