contract GSUMedal is ERC20Interface, Owned, SafeMath {
    event MedalTransfer(address indexed from, address indexed to, uint tokens);
    
    string public medalSymbol;
    string public medalName;
    uint8 public medalDecimals;
    uint public _medalTotalSupply;

    mapping(address => uint) medalBalances;
    mapping(address => bool) medalFreezed;
    mapping(address => uint) medalFreezeAmount;
    mapping(address => uint) medalUnlockTime;


    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------
    function GSUMedal() public {
        medalSymbol = "GSU";
        medalName = "Anno Consensus";
        medalDecimals = 0;
        _medalTotalSupply = 1000000;
        medalBalances[msg.sender] = _medalTotalSupply;
        MedalTransfer(address(0), msg.sender, _medalTotalSupply);
    }


    // ------------------------------------------------------------------------
    // Total supply
    // ------------------------------------------------------------------------
    function medalTotalSupply() public constant returns (uint) {
        return _medalTotalSupply  - medalBalances[address(0)];
    }


    // ------------------------------------------------------------------------
    // Get the token balance for account tokenOwner
    // ------------------------------------------------------------------------
    function mentalBalanceOf(address tokenOwner) public constant returns (uint balance) {
        return medalBalances[tokenOwner];
    }


    // ------------------------------------------------------------------------
    // Transfer the balance from token owner's account to to account
    // - Owner's account must have sufficient balance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function medalTransfer(address to, uint tokens) public returns (bool success) {
        if(medalFreezed[msg.sender] == false){
            medalBalances[msg.sender] = safeSub(medalBalances[msg.sender], tokens);
            medalBalances[to] = safeAdd(medalBalances[to], tokens);
            MedalTransfer(msg.sender, to, tokens);
        } else {
            if(medalBalances[msg.sender] > medalFreezeAmount[msg.sender]) {
                require(tokens <= safeSub(medalBalances[msg.sender], medalFreezeAmount[msg.sender]));
                medalBalances[msg.sender] = safeSub(medalBalances[msg.sender], tokens);
                medalBalances[to] = safeAdd(medalBalances[to], tokens);
                MedalTransfer(msg.sender, to, tokens);
            }
        }
            
        return true;
    }

    // ------------------------------------------------------------------------
    // Mint Tokens
    // ------------------------------------------------------------------------
    function mintMedal(uint amount) public onlyOwner {
        medalBalances[msg.sender] = safeAdd(medalBalances[msg.sender], amount);
        _medalTotalSupply = safeAdd(_medalTotalSupply, amount);
    }

    // ------------------------------------------------------------------------
    // Burn Tokens
    // ------------------------------------------------------------------------
    function burnMedal(uint amount) public onlyOwner {
        medalBalances[msg.sender] = safeSub(medalBalances[msg.sender], amount);
        _medalTotalSupply = safeSub(_medalTotalSupply, amount);
    }
    
    // ------------------------------------------------------------------------
    // Freeze Tokens
    // ------------------------------------------------------------------------
    function medalFreeze(address user, uint amount, uint period) public onlyOwner {
        require(medalBalances[user] >= amount);
        medalFreezed[user] = true;
        medalUnlockTime[user] = uint(now) + period;
        medalFreezeAmount[user] = amount;
    }
    
    function _medalFreeze(uint amount) internal {
        require(medalBalances[msg.sender] >= amount);
        medalFreezed[msg.sender] = true;
        medalUnlockTime[msg.sender] = uint(-1);
        medalFreezeAmount[msg.sender] = amount;
    }

    // ------------------------------------------------------------------------
    // UnFreeze Tokens
    // ------------------------------------------------------------------------
    function medalUnFreeze() public {
        require(medalFreezed[msg.sender] == true);
        require(medalUnlockTime[msg.sender] < uint(now));
        medalFreezed[msg.sender] = false;
        medalFreezeAmount[msg.sender] = 0;
    }
    
    function _medalUnFreeze() internal {
        require(medalFreezed[msg.sender] == true);
        medalUnlockTime[msg.sender] = 0;
        medalFreezed[msg.sender] = false;
        medalFreezeAmount[msg.sender] = 0;
    }
    
    function medalIfFreeze(address user) public view returns (
        bool check, 
        uint amount, 
        uint timeLeft
    ) {
        check = medalFreezed[user];
        amount = medalFreezeAmount[user];
        timeLeft = medalUnlockTime[user] - uint(now);
    }

}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and assisted
// token transfers
// ----------------------------------------------------------------------------
function medalUnFreeze() public {
    require(medalFreezed[msg.sender] == true);
    require(medalUnlockTime[msg.sender] < uint(now));
    medalFreezed[msg.sender] = false;
    medalFreezeAmount[msg.sender] = 0;
}

// ------------------------------------------------------------------------
// UnFreeze Tokens
// ------------------------------------------------------------------------