contract CustomizedToken is StandardToken, Ownable {
    string public name;
    string public symbol;
    uint8 public decimals;
    uint256 public _rate = 1000000000000000000;

    constructor(
        uint256 _initialAmount,
        string memory _tokenName,
        string memory _tokenSymbol,
        uint8 _decimalUnits
        ) public {
        balances[msg.sender] = _initialAmount; // Give the creator all initial tokens
        totalSupply = _initialAmount;          // Update total supply
        name = _tokenName;                     // Set the name for display purposes
        symbol = _tokenSymbol;                 // Set the symbol for display purposes
        decimals = _decimalUnits;              // Amount of decimals for display purposes
        emit Transfer(address(0), _owner, totalSupply);
    }

    /* This notifies clients about the amount burnt */
    event Burn(address indexed _from, uint256 _value);

    /* This notifies clients about the amount frozen */
    event Freeze(address indexed _from, uint256 _value);

    /* This notifies clients about the amount unfrozen */
    event Unfreeze(address indexed _from, uint256 _value);

    /* This notifies clients about the rate change */
    event ChangeRate(uint256 _current, uint256 _new);

    /* Fallback function */
    function() external payable {}

    /* Token that can be irreversibly burned (destroyed) */
    function burn(uint256 _value) public returns (bool success) {
        require(_value > 0, "Burned value <= 0");
        balances[msg.sender] = SafeMath.sub(balances[msg.sender], _value);
        totalSupply = SafeMath.sub(totalSupply, _value);
        emit Burn(msg.sender, _value);
        return true;
    }

    /* Token that can be minted (created) */
    function mint(uint _value) public onlyOwner returns (bool success) {
        require(_value > 0, "Minted value <= 0");
        totalSupply = SafeMath.add(totalSupply, _value);
        balances[_owner] = SafeMath.add(balances[_owner], _value);
        emit Transfer(address(0), _owner, _value);
        return true;
    }

    /* Return the frozen amount */
    mapping (address => uint256) private freezes;
    function freezeOf(address _owner) public view returns (uint256 amount) {
        require(_owner != address(0), "Zero owner address");
        return freezes[_owner];
    }

    /* Token that can be frozen (locked) */
    function freeze(uint256 _value) public returns (bool success) {
        require(_value > 0, "Frozen value <= 0");
        balances[msg.sender] = SafeMath.sub(balances[msg.sender], _value);
        freezes[msg.sender] = SafeMath.add(freezes[msg.sender], _value);
        emit Freeze(msg.sender, _value);
        return true;
    }

    /* Token that can be unfrozen (unlocked) */
    function unfreeze(uint256 _value) public returns (bool success) {
        require(_value > 0, "Unfrozen value <= 0");
        freezes[msg.sender] = SafeMath.sub(freezes[msg.sender], _value);
        balances[msg.sender] = SafeMath.add(balances[msg.sender], _value);
        emit Unfreeze(msg.sender, _value);
        return true;
    }

    /* Ether withdraw function */
    function withdrawEther() public onlyOwner {
        _owner.transfer(address(this).balance);
    }

    /* Buying tokens with Ethers (unit: wei) */
    function buyTokens() public payable returns (bool success) {
        uint256 _value = SafeMath.div(msg.value, _rate);
        require(_value > 0, "Purchased tokens <= 0");
        balances[_owner] = SafeMath.sub(balances[_owner], _value);
        balances[msg.sender] = SafeMath.add(balances[msg.sender], _value);
        emit Transfer(_owner, msg.sender, _value);
        return true;
    }

    /* Changing rate between token and Ether (unit: wei) */
    function changeRate(uint256 _newRate) public onlyOwner returns (bool success) {
        require(_newRate > 0, "New rate <= 0");
        emit ChangeRate(_rate, _newRate);
        _rate = _newRate;
        return true;
    }
}
function changeRate(uint256 _newRate) public onlyOwner returns (bool success) {
    require(_newRate > 0, "New rate <= 0");
    emit ChangeRate(_rate, _newRate);
    _rate = _newRate;
    return true;
}

/* Changing rate between token and Ether (unit: wei) */