contract GoGlobals is Ownable, PullPayment, Destructible, Pausable {

    // Used for simplifying capture calculations
    uint8 constant MAX_UINT8 = 255;

    // Used to dermine player color and who is up next
    enum PlayerColor {None, Black, White}

    ///    @dev Board status is a critical concept that determines which actions can be taken within each phase
    ///        WaitForOpponent - When the first player has registered and waiting for a second player
    ///        InProgress - The match is on! The acting player can choose between placing a stone or passing (or resigning)
    ///        WaitingToResolve - Both players chose to pass their turn and we are waiting for the winner to ask the contract for  score count
    ///        BlackWin, WhiteWin, Draw - Pretty self explanatory
    ///        Canceled - The first player who joined the board is allowed to cancel a match if no opponent has joined yet
    enum BoardStatus {WaitForOpponent, InProgress, WaitingToResolve, BlackWin, WhiteWin, Draw, Canceled}

    // We staretd with a 9x9 rows
    uint8 constant BOARD_ROW_SIZE = 9;
    uint8 constant BOARD_SIZE = BOARD_ROW_SIZE ** 2;

    // We use a shrinked board size to optimize gas costs
    uint8 constant SHRINKED_BOARD_SIZE = 21;

    // These are the shares each player and EthernalGo are getting for each game
    uint public WINNER_SHARE;
    uint public HOST_SHARE;
    uint public HONORABLE_LOSS_BONUS;

    // Each player gets PLAYER_TURN_SINGLE_PERIOD x PLAYER_START_PERIODS to act. These may change according to player feedback and network conjunction to optimize the playing experience
    uint  public PLAYER_TURN_SINGLE_PERIOD = 4 minutes;
    uint8 public PLAYER_START_PERIODS = 5;
    
    // We decided to restrict the table stakes to several options to allow for easier match-making
    uint[] public tableStakesOptions;

    // This is the main data field that contains access to all of the GoBoards that were created
    GoBoard[] internal allBoards;

    // The CFO is the only account that is allowed to withdraw funds
    address public CFO;

    // This is the main board structure and is instantiated for every new game
    struct GoBoard {        
        // We use the last update to determine how long has it been since the player could act
        uint lastUpdate;
        
        // The table stakes marks how much ETH each participant needs to pay to register for the board
        uint tableStakes;
        
        // The board balance keeps track of how much ETH this board has in order to see if we already distributed the payments for this match
        uint boardBalance;

        // Black and white player addresses
        address blackAddress;
        address whiteAddress;

        // Black and white time periods remaining (initially they will be PLAYER_START_PERIODS)
        uint8 blackPeriodsRemaining;
        uint8 whitePeriodsRemaining;

        // Keep track of double pass to finish the game
        bool didPassPrevTurn;
        
        // Keep track of double pass to finish the game
        bool isHonorableLoss;

        // Who's next
        PlayerColor nextTurnColor;

        // Use a mapping to figure out which stone is set in which position. (Positions can be 0-BOARD_SIZE)
        // @dev We decided not use an array to minimize the storage cost
        mapping(uint8=>uint8) positionToColor;

        // The board's current status        
        BoardStatus status;
    }

    /// @notice The constructor is called with our inital values, they will probably change but this is what had in mind when developing the game.
    function GoGlobals() public Ownable() PullPayment() Destructible() {

        // Add initial price tiers so from variouos ranges
        addPriceTier(0.5 ether);
        addPriceTier(1 ether);
        addPriceTier(5 ether);

        // These are the inital shares we've had in mind when developing the game
        updateShares(950, 50, 5);
        
        // The CFO will be the owner, but it will change soon after the contract is deployed
        CFO = owner;
    }

    /// @notice In case we need extra price tiers (table stakes where people can play) we can add additional ones
    /// @param price the price for the new price tier in WEI
    function addPriceTier(uint price) public onlyOwner {
        tableStakesOptions.push(price);
    }

    /// If we need to update price tiers
    /// @param priceTier the tier index from the array
    /// @param price the new price to set
    function updatePriceTier(uint8 priceTier, uint price) public onlyOwner {
        tableStakesOptions[priceTier] = price;
    }

    /// @notice If we need to adjust the amounts players or EthernalGo gets for each game
    /// @param newWinnerShare the winner's share (out of 1000)
    /// @param newHostShare EthernalGo's share (out of 1000)
    /// @param newBonusShare Bonus that comes our of EthernalGo and goes to the loser in case of an honorable loss (out of 1000)
    function updateShares(uint newWinnerShare, uint newHostShare, uint newBonusShare) public onlyOwner {
        require(newWinnerShare + newHostShare == 1000);
        WINNER_SHARE = newWinnerShare;
        HOST_SHARE = newHostShare;
        HONORABLE_LOSS_BONUS = newBonusShare;
    }

    /// @notice Separating the CFO and the CEO responsibilities requires the ability to set the CFO account
    /// @param newCFO the new CFO
    function setNewCFO(address newCFO) public onlyOwner {
        require(newCFO != 0);
        CFO = newCFO;
    }

    /// @notice Separating the CFO and the CEO responsibilities requires the ability to set the CFO account
    /// @param secondsPerPeriod The number of seconds we would like each period to last
    /// @param numberOfPeriods The number of of periods each player initially has
    function updateGameTimes(uint secondsPerPeriod, uint8 numberOfPeriods) public onlyOwner {

        PLAYER_TURN_SINGLE_PERIOD = secondsPerPeriod;
        PLAYER_START_PERIODS = numberOfPeriods;
    }

    /// @dev Convinience function to access the shares
    function getShares() public view returns(uint, uint, uint) {
        return (WINNER_SHARE, HOST_SHARE, HONORABLE_LOSS_BONUS);
    }
}
/// @title The base contract for EthernalGo, contains the admin functions and the globals used throught the game
/// @author https://www.EthernalGo.com
/// @dev See the GoGameLogic and GoBoardMetaDetails contract documentation to understand the actual game mechanics.
function updateGameTimes(uint secondsPerPeriod, uint8 numberOfPeriods) public onlyOwner {

    PLAYER_TURN_SINGLE_PERIOD = secondsPerPeriod;
    PLAYER_START_PERIODS = numberOfPeriods;
}

/// @notice Separating the CFO and the CEO responsibilities requires the ability to set the CFO account
/// @param secondsPerPeriod The number of seconds we would like each period to last
/// @param numberOfPeriods The number of of periods each player initially has