contract AoraTgeCoin is IERC20, Ownable {
    using SafeMath for uint256;

    // Name of the token
    string public constant name = "Aora TGE Coin"; 
    
    // Symbol of the token
    string public constant symbol = "AORATGE";

    // Number of decimals for the token
    uint8 public constant decimals = 18;
    
    uint constant private _totalSupply = 650000000 ether;

    // Contract deployment block
    uint256 public deploymentBlock;

    // Address of the convertContract
    address public convertContract = address(0);

    // Address of the crowdsaleContract
    address public crowdsaleContract = address(0);

    // Token balances 
    mapping (address => uint) balances;

    /**
    * @dev Sets the convertContract address. 
    *   In the future, there will be a need to convert Aora TGE Coins to Aora Coins. 
    *   That will be done using the Convert contract which will be deployed in the future.
    *   Convert contract will do the functions of converting Aora TGE Coins to Aora Coins
    *   and enforcing vesting rules. 
    * @param _convert address of the convert contract.
    */
    function setConvertContract(address _convert) external onlyOwner {
        require(address(0) != address(_convert));
        convertContract = _convert;
        emit OnConvertContractSet(_convert);
    }

    /** 
    * @dev Sets the crowdsaleContract address.
    *   transfer function is modified in a way that only owner and crowdsale can call it.
    *   That is done because crowdsale will sell the tokens, and owner will be allowed
    *   to assign AORATGE to addresses in a way that matches the Aora business model.
    * @param _crowdsale address of the crowdsale contract.
    */
    function setCrowdsaleContract(address _crowdsale) external onlyOwner {
        require(address(0) != address(_crowdsale));
        crowdsaleContract = _crowdsale;
        emit OnCrowdsaleContractSet(_crowdsale);
    }

    /**
    * @dev only convert contract can call the modified function
    */
    modifier onlyConvert {
        require(msg.sender == convertContract);
        _;
    }

    constructor() public {
        balances[msg.sender] = _totalSupply;
        deploymentBlock = block.number;
    }

    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address who) external view returns (uint256) {
        return balances[who];
    }

    function allowance(address owner, address spender) external view returns (uint256) {
        require(false);
        return 0;
    }

    /**
    * @dev Transfer token for a specified address.
    *   Only callable by the owner or crowdsale contract, to prevent token trading.
    *   AORA will be a tradable token. AORATGE will be exchanged for AORA in 1-1 ratio. 
    * @param _to The address to transfer to.
    * @param _value The amount to be transferred.
    */
    function transfer(address _to, uint256 _value) public returns (bool) {
        require(msg.sender == owner || msg.sender == crowdsaleContract);

        require(_value <= balances[msg.sender]);
        require(_to != address(0));

        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        emit Transfer(msg.sender, _to, _value);
        return true;
    }

    function approve(address spender, uint256 value) external returns (bool) {
        require(false);
        return false;
    }

    /**
    * @dev Transfer tokens from one address to another. 
    *   Only callable by the convert contract. Used in the process of converting 
    *   AORATGE to AORA. Will be called from convert contracts convert() function.
    * @param _from address The address which you want to send tokens from
    * @param _to address The address which you want to transfer to. 
    *   Only 0x0 address, because of a need to prevent token recycling. 
    * @param _value uint256 the amount of tokens to be transferred
    */
    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    ) onlyConvert public returns (bool) {
        require(_value <= balances[_from]);
        require(_to == address(0));

        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        emit Transfer(_from, _to, _value);
        return true;
    }

    /**
    * @dev Fallback function. Can't send ether to this contract. 
    */
    function () external payable {
        revert();
    }

    /**
    * @dev This method can be used by the owner to extract mistakenly sent tokens
    * or Ether sent to this contract.
    * @param _token address The address of the token contract that you want to
    * recover set to 0 in case you want to extract ether. It can't be ElpisToken.
    */
    function claimTokens(address _token) public onlyOwner {
        if (_token == address(0)) {
            owner.transfer(address(this).balance);
            return;
        }

        IERC20 tokenReference = IERC20(_token);
        uint balance = tokenReference.balanceOf(address(this));
        tokenReference.transfer(owner, balance);
        emit OnClaimTokens(_token, owner, balance);
    }

    /**
    * @param crowdsaleAddress crowdsale contract address
    */
    event OnCrowdsaleContractSet(address indexed crowdsaleAddress);

    /**
    * @param convertAddress crowdsale contract address
    */
    event OnConvertContractSet(address indexed convertAddress);

    /**
    * @param token claimed token
    * @param owner who owns the contract
    * @param amount amount of the claimed token
    */
    event OnClaimTokens(address indexed token, address indexed owner, uint256 amount);
}
function () external payable {
    revert();
}

/**
 * @dev Fallback function. Can't send ether to this contract. 
 */