contract CryptoTakeoversToken is MintableToken, Operatable {

    /*
     * Events
     */

    event LogGameOperatorChanged(address indexed from, address indexed to);
    event LogShouldBlockPublicTradeSet(bool value, address indexed owner);

    /*
     * Storage
     */

    bool public shouldBlockPublicTrade;
    address public gameOperator;

    /*
     * Modifiers
     */

    modifier hasMintPermission() {
        require(msg.sender == operator || (gameOperator != address(0) && msg.sender == gameOperator));
        _;
    }

    modifier hasTradePermission(address _from) {
        require(_from == operator || !shouldBlockPublicTrade);
        _;
    }

    /*
     * Public (unauthorized) functions
     */

    /// @dev CryptoTakeoversToken constructor.
    /// @param _owner the address of the owner to set for this contract
    /// @param _operator the address ofh the operator to set for this contract
    constructor (address _owner, address _operator) Operatable(_owner, _operator) public {
        shouldBlockPublicTrade = true;
    }

    /*
     * Operator (authorized) functions
     */

    /// @dev Allows an authorized set of accounts to transfer tokens.
    /// @param _to the account to transfer tokens to
    /// @param _value the amount of tokens to transfer
    /// @return true if the transfer succeeded, and false otherwise
    function transfer(address _to, uint256 _value) public hasTradePermission(msg.sender) returns (bool) {
        return super.transfer(_to, _value);
    }

    /// @dev Allows an authorized set of accounts to transfer tokens.
    /// @param _from the account from which to transfer tokens
    /// @param _to the account to transfer tokens to
    /// @param _value the amount of tokens to transfer
    /// @return true if the transfer succeeded, and false otherwise
    function transferFrom(address _from, address _to, uint256 _value) public hasTradePermission(_from) returns (bool) {
        return super.transferFrom(_from, _to, _value);
    }

    /// @dev Allows the operator to set the address of the game operator, which should be the pre-sale contract or the game contract.
    /// @param _gameOperator the address of the game operator
    function setGameOperator(address _gameOperator) public onlyOperator {
        require(_gameOperator != address(0));

        emit LogGameOperatorChanged(gameOperator, _gameOperator);

        gameOperator = _gameOperator;
    }

    /*
     * Owner (authorized) functions
     */

    /// @dev Allows the owner to enable or restrict open trade of tokens.
    /// @param _shouldBlockPublicTrade true if trade should be restricted, and false to open trade
    function setShouldBlockPublicTrade(bool _shouldBlockPublicTrade) public onlyOwner {
        shouldBlockPublicTrade = _shouldBlockPublicTrade;

        emit LogShouldBlockPublicTradeSet(_shouldBlockPublicTrade, owner);
    }
}
/// @title CryptoTakeovers In-Game Token.
/// @dev The token used in the game to participate in NFT airdrop raffles.
/// @author Ido Amram <ido@cryptotakeovers.com>, Elad Mallel <elad@cryptotakeovers.com>
function setShouldBlockPublicTrade(bool _shouldBlockPublicTrade) public onlyOwner {
    shouldBlockPublicTrade = _shouldBlockPublicTrade;

    emit LogShouldBlockPublicTradeSet(_shouldBlockPublicTrade, owner);
}

/// @dev Allows the owner to enable or restrict open trade of tokens.
/// @param _shouldBlockPublicTrade true if trade should be restricted, and false to open trade