contract XMLYBadge is ERC20Interface, Administration, SafeMath {
    event BadgeTransfer(address indexed from, address indexed to, uint tokens);
    
    string public badgeSymbol;
    string public badgeName;
    uint8 public badgeDecimals;
    uint public _badgeTotalSupply;

    mapping(address => uint) badgeBalances;
    mapping(address => bool) badgeFreezed;
    mapping(address => uint) badgeFreezeAmount;
    mapping(address => uint) badgeUnlockTime;


    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------
    function XMLYBadge() public {
        badgeSymbol = "XMH";
        badgeName = "XMLY Honor";
        badgeDecimals = 0;
        _badgeTotalSupply = 1000;
        badgeBalances[CFOAddress] = _badgeTotalSupply;
        BadgeTransfer(address(0), CFOAddress, _badgeTotalSupply);
    }


    // ------------------------------------------------------------------------
    // Total supply
    // ------------------------------------------------------------------------
    function badgeTotalSupply() public constant returns (uint) {
        return _badgeTotalSupply  - badgeBalances[address(0)];
    }


    // ------------------------------------------------------------------------
    // Get the token balance for account tokenOwner
    // ------------------------------------------------------------------------
    function badgeBalanceOf(address tokenOwner) public constant returns (uint balance) {
        return badgeBalances[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 badgeTransfer(address to, uint tokens) public whenNotPaused returns (bool success) {
        if(badgeFreezed[msg.sender] == false){
            badgeBalances[msg.sender] = safeSub(badgeBalances[msg.sender], tokens);
            badgeBalances[to] = safeAdd(badgeBalances[to], tokens);
            BadgeTransfer(msg.sender, to, tokens);
        } else {
            if(badgeBalances[msg.sender] > badgeFreezeAmount[msg.sender]) {
                require(tokens <= safeSub(badgeBalances[msg.sender], badgeFreezeAmount[msg.sender]));
                badgeBalances[msg.sender] = safeSub(badgeBalances[msg.sender], tokens);
                badgeBalances[to] = safeAdd(badgeBalances[to], tokens);
                BadgeTransfer(msg.sender, to, tokens);
            }
        }
            
        return true;
    }

    // ------------------------------------------------------------------------
    // Mint Tokens
    // ------------------------------------------------------------------------
    function mintBadge(uint amount) public onlyAdmin {
        badgeBalances[msg.sender] = safeAdd(badgeBalances[msg.sender], amount);
        _badgeTotalSupply = safeAdd(_badgeTotalSupply, amount);
    }

    // ------------------------------------------------------------------------
    // Burn Tokens
    // ------------------------------------------------------------------------
    function burnBadge(uint amount) public onlyAdmin {
        badgeBalances[msg.sender] = safeSub(badgeBalances[msg.sender], amount);
        _badgeTotalSupply = safeSub(_badgeTotalSupply, amount);
    }
    
    // ------------------------------------------------------------------------
    // Freeze Tokens
    // ------------------------------------------------------------------------
    function badgeFreeze(address user, uint amount, uint period) public onlyAdmin {
        require(badgeBalances[user] >= amount);
        badgeFreezed[user] = true;
        badgeUnlockTime[user] = uint(now) + period;
        badgeFreezeAmount[user] = amount;
    }
    
    function _badgeFreeze(uint amount) internal {
        require(badgeFreezed[msg.sender] == false);
        require(badgeBalances[msg.sender] >= amount);
        badgeFreezed[msg.sender] = true;
        badgeUnlockTime[msg.sender] = uint(-1);
        badgeFreezeAmount[msg.sender] = amount;
    }

    // ------------------------------------------------------------------------
    // UnFreeze Tokens
    // ------------------------------------------------------------------------
    function badgeUnFreeze() public whenNotPaused {
        require(badgeFreezed[msg.sender] == true);
        require(badgeUnlockTime[msg.sender] < uint(now));
        badgeFreezed[msg.sender] = false;
        badgeFreezeAmount[msg.sender] = 0;
    }
    
    function _badgeUnFreeze(uint _amount) internal {
        require(badgeFreezed[msg.sender] == true);
        badgeUnlockTime[msg.sender] = 0;
        badgeFreezed[msg.sender] = false;
        badgeFreezeAmount[msg.sender] = safeSub(badgeFreezeAmount[msg.sender], _amount);
    }
    
    function badgeIfFreeze(address user) public view returns (
        bool check, 
        uint amount, 
        uint timeLeft
    ) {
        check = badgeFreezed[user];
        amount = badgeFreezeAmount[user];
        timeLeft = badgeUnlockTime[user] - uint(now);
    }

}
function mintBadge(uint amount) public onlyAdmin {
    badgeBalances[msg.sender] = safeAdd(badgeBalances[msg.sender], amount);
    _badgeTotalSupply = safeAdd(_badgeTotalSupply, amount);
}

// ------------------------------------------------------------------------
// Mint Tokens
// ------------------------------------------------------------------------