contract MAJz is ERC20Token, Ownership {
    using SafeMath for uint256;

    string public symbol;
    string public name;
    uint256 public decimals;
    uint256 public totalSupply;

    mapping(address => uint256) public balances;
    mapping(address => mapping(address => uint256)) allowed;
    
    //Constructor of the Token
    constructor() public{
        symbol = "MAZ";
        name = "MAJz";
        decimals = 18;
        totalSupply = 560000000000000000000000000;
        balances[msg.sender] = totalSupply;
        owner = msg.sender;
        emit Transfer(address(0), msg.sender, totalSupply); 
    }


    /****************************************************************************
    *                   Basic Token Functions                                   *
    ****************************************************************************/
    //Returns the totalSupply
    function totalSupply() public view returns (uint256) {
        return totalSupply;
    }
    //Return the balance of an specified account
    function balanceOf(address _targetAddress) public view returns (uint256) {
        return balances[_targetAddress];
    }
    
    //Transfer function. Validates targetAdress not to be 0x0
    function transfer(address _targetAddress, uint256 _value) validDestination(_targetAddress) public returns (bool) {
        balances[msg.sender] = SafeMath.sub(balances[msg.sender], _value); //SafeMath will throw if value > balance
        balances[_targetAddress] = SafeMath.add(balances[_targetAddress], _value);
        emit Transfer(msg.sender, _targetAddress, _value); 
        return true; 
    }

    /****************************************************************************
    *                   ERC20 Token Functions                                   *
    ****************************************************************************/
    function allowance(address _originAddress, address _targetAddress) public view returns (uint256){
        return allowed[_originAddress][_targetAddress];
    }

    function approve(address _targetAddress, uint256 _value) public returns (bool) {
        allowed[msg.sender][_targetAddress] = _value;
        emit Approval(msg.sender, _targetAddress, _value);
        return true;
    }

    function transferFrom(address _originAddress, address _targetAddress, uint256 _value) public returns (bool) {
        balances[_originAddress] = SafeMath.sub(balances[_originAddress], _value); //SafeMath will throw if _value> balanceOf[_originAddress]
        allowed[_originAddress][msg.sender] = SafeMath.sub(allowed[_originAddress][msg.sender], _value); //SafeMath will throw if _value > allowance
        balances[_targetAddress] = SafeMath.add(balances[_targetAddress], _value);
        emit Transfer(_originAddress, _targetAddress, _value);
        return true;
    }

    function () public payable {
        revert();
    }

    /****************************************************************************
    *                   Extended Functionalites                                 *
    ****************************************************************************/

    //Burn the specified amount (_value) of tokens
    function burnTokens(uint256 _value) public onlyOwner returns (bool){
        balances[owner] = SafeMath.sub(balances[owner], _value); //SafeMath will throw if value > balance
        totalSupply = SafeMath.sub(totalSupply, _value);
        emit BurnTokens(_value);
        return true;
    }

    //Emit new tokens
    function emitTokens(uint256 _value) public onlyOwner returns (bool){
        balances[owner] = SafeMath.add(balances[owner], _value); //SafeMath will throw if Overflow
        totalSupply = SafeMath.add(totalSupply, _value);
        emit EmitTokens(_value);
        return true;
    }

    //Revert a transfer in case of error. onlyOwner
    function revertTransfer(address _targetAddress, uint256 _value) public onlyOwner returns (bool) {
        balances[_targetAddress] = SafeMath.sub(balances[_targetAddress], _value);
        balances[owner] = SafeMath.add(balances[owner], _value);
        emit RevertTransfer(_targetAddress, _value);
        return true;
    }
    
    event RevertTransfer(address _targetAddress, uint256 _value);
    event BurnTokens(uint256 _value);
    event EmitTokens(uint256 _value);
}
/****************************************************************************
 *                       The Token Contract                                  *
 *                       with Extended funtionalities                        *
 ****************************************************************************/
function totalSupply() public view returns (uint256) {
        return totalSupply;
    }
//Returns the totalSupply