contract MoInkeGold is ERC20Interface, Administration, SafeMath {
    event GoldTransfer(address indexed from, address indexed to, uint tokens);
    
    string public goldSymbol;
    string public goldName;
    uint8 public goldDecimals;
    uint public _goldTotalSupply;

    mapping(address => uint) goldBalances;
    mapping(address => bool) goldFreezed;
    mapping(address => uint) goldFreezeAmount;
    mapping(address => uint) goldUnlockTime;


    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------
    constructor() public {
        goldSymbol = "MIG";
        goldName = "MoInke Gold";
        goldDecimals = 0;
        _goldTotalSupply = 180000;
        goldBalances[CEOAddress] = _goldTotalSupply;
        emit GoldTransfer(address(0), CEOAddress, _goldTotalSupply);
    }

    // ------------------------------------------------------------------------
    // Total supply
    // ------------------------------------------------------------------------
    function goldTotalSupply() public constant returns (uint) {
        return _goldTotalSupply  - goldBalances[address(0)];
    }


    // ------------------------------------------------------------------------
    // Get the token balance for account tokenOwner
    // ------------------------------------------------------------------------
    function goldBalanceOf(address tokenOwner) public constant returns (uint balance) {
        return goldBalances[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 goldTransfer(address to, uint tokens) public ifGoldTrans returns (bool success) {
        if(goldFreezed[msg.sender] == false){
            goldBalances[msg.sender] = safeSub(goldBalances[msg.sender], tokens);
            goldBalances[to] = safeAdd(goldBalances[to], tokens);
            emit GoldTransfer(msg.sender, to, tokens);
        } else {
            if(goldBalances[msg.sender] > goldFreezeAmount[msg.sender]) {
                require(tokens <= safeSub(goldBalances[msg.sender], goldFreezeAmount[msg.sender]));
                goldBalances[msg.sender] = safeSub(goldBalances[msg.sender], tokens);
                goldBalances[to] = safeAdd(goldBalances[to], tokens);
                emit GoldTransfer(msg.sender, to, tokens);
            }
        }
            
        return true;
    }

    // ------------------------------------------------------------------------
    // Mint Tokens
    // ------------------------------------------------------------------------
    function mintGold(uint amount) public onlyCEO {
        goldBalances[msg.sender] = safeAdd(goldBalances[msg.sender], amount);
        _goldTotalSupply = safeAdd(_goldTotalSupply, amount);
    }

    // ------------------------------------------------------------------------
    // Burn Tokens
    // ------------------------------------------------------------------------
    function burnGold(uint amount) public onlyCEO {
        goldBalances[msg.sender] = safeSub(goldBalances[msg.sender], amount);
        _goldTotalSupply = safeSub(_goldTotalSupply, amount);
    }
    
    // ------------------------------------------------------------------------
    // Freeze Tokens
    // ------------------------------------------------------------------------
    function goldFreeze(address user, uint amount, uint period) public onlyAdmin {
        require(goldBalances[user] >= amount);
        goldFreezed[user] = true;
        goldUnlockTime[user] = uint(now) + period;
        goldFreezeAmount[user] = amount;
    }
    
    function _goldFreeze(uint amount) internal {
        require(goldFreezed[msg.sender] == false);
        require(goldBalances[msg.sender] >= amount);
        goldFreezed[msg.sender] = true;
        goldUnlockTime[msg.sender] = uint(-1);
        goldFreezeAmount[msg.sender] = amount;
    }

    // ------------------------------------------------------------------------
    // UnFreeze Tokens
    // ------------------------------------------------------------------------
    function goldUnFreeze() public whenNotPaused {
        require(goldFreezed[msg.sender] == true);
        require(goldUnlockTime[msg.sender] < uint(now));
        goldFreezed[msg.sender] = false;
        goldFreezeAmount[msg.sender] = 0;
    }
    
    function _goldUnFreeze(uint _amount) internal {
        require(goldFreezed[msg.sender] == true);
        goldUnlockTime[msg.sender] = 0;
        goldFreezed[msg.sender] = false;
        goldFreezeAmount[msg.sender] = safeSub(goldFreezeAmount[msg.sender], _amount);
    }
    
    function goldIfFreeze(address user) public view returns (
        bool check, 
        uint amount, 
        uint timeLeft
    ) {
        check = goldFreezed[user];
        amount = goldFreezeAmount[user];
        timeLeft = goldUnlockTime[user] - uint(now);
    }

}
function goldTotalSupply() public constant returns (uint) {
    return _goldTotalSupply  - goldBalances[address(0)];
}

// ------------------------------------------------------------------------
// Total supply
// ------------------------------------------------------------------------