contract BimCoinToken is owned, TokenERC20 {

    FiatContract private fiatService;
    uint256 public buyPrice;
    bool private useFiatService;
    bool private onSale;
    uint256 private buyPriceInCent;
    uint256 private etherPerCent;
    uint256 constant TOKENS_PER_DOLLAR = 100000;
    uint256 storageAmount;
    address store;

    mapping (address => bool) public frozenAccount;

    /* This generates a public event on the blockchain that will notify clients */
    event FrozenFunds(address target, bool frozen);

    /* Initializes contract with initial supply tokens to the creator of the contract */
    constructor(
        uint256 initialSupply,
        string tokenName,
        string tokenSymbol,
        bool _useFiatContract
    ) TokenERC20(initialSupply, tokenName, tokenSymbol) public {
        fiatService = FiatContract(0x8055d0504666e2B6942BeB8D6014c964658Ca591);
        useFiatService = _useFiatContract;
        buyPriceInCent = 100;
        onSale = true;
        storageAmount = (2 * (initialSupply * 10 ** uint256(decimals)))/10;
        store = msg.sender;
    }

    /* Internal transfer, only can be called by this contract */
    function _transfer(address _from, address _to, uint _value) internal {
        require (_to != 0x0);                               // Prevent transfer to 0x0 address. Use burn() instead
        require (balanceOf[_from] >= _value);               // Check if the sender has enough
        require (balanceOf[_to] + _value >= balanceOf[_to]); // Check for overflows
        require(!frozenAccount[_from]);                     // Check if sender is frozen
        require(!frozenAccount[_to]);                       // Check if recipient is frozen
        balanceOf[_from] -= _value;                         // Subtract from the sender
        balanceOf[_to] += _value;                           // Add the same to the recipient
        emit Transfer(_from, _to, _value);
    }

    /// @notice `freeze? Prevent | Allow` `target` from sending & receiving tokens
    /// @param target Address to be frozen
    /// @param freeze either to freeze it or not
    function freezeAccount(address target, bool freeze) onlyOwner public {
        frozenAccount[target] = freeze;
        emit FrozenFunds(target, freeze);
    }

    /// @notice Allow users to buy tokens for `newBuyPrice` eth
    /// @param newBuyPrice Price users can buy from the contract
    function setPrice(uint256 newBuyPrice) onlyOwner public {
        buyPrice = newBuyPrice;
    }
    
    /// @notice Allow users to buy tokens for `newBuyPrice` eth
    /// @param newBuyPrice Price users can buy from the contract
    function setPriceInCents(uint256 newBuyPrice) onlyOwner public {
        buyPriceInCent = newBuyPrice;
    }
    
    /// @notice Buy tokens from contract by sending ether
    function () payable public {
        buy();
    }

    /// @notice Buy tokens from contract by sending ether
    function buy() payable public {
        require(onSale);
        
        uint256 price = getPrice();
        
        uint amount = msg.value * TOKENS_PER_DOLLAR * 10 ** uint256(decimals) / price;               // calculates the amount
        
        require(balanceOf[owner] - amount >= storageAmount);
        
        store.transfer(msg.value);
        
        _transfer(owner, msg.sender, amount);              // makes the transfers
    }
    
    function getPrice() private view returns (uint256){
        if(useFiatService){
            return fiatService.USD(0) * buyPriceInCent;
        }else{
            return etherPerCent * buyPriceInCent;
        }
    }
    
    function setUseService(bool status) external onlyOwner{
        useFiatService = status;
    }
    
    function setEtherCentPrice(uint256 _newValue) external onlyOwner {
        etherPerCent = (10 ** uint256(decimals))/(_newValue);
    }
    
    function setStore(address _newValue) external onlyOwner {
        store = _newValue;
    }
    
    function toggleSale(bool _value) external onlyOwner {
        onSale = _value;
    }
    
    function withdraw() external onlyOwner {
        uint balance = address(this).balance;
        if(balance > 0){
            store.transfer(balance);
        }
    }
}
/******************************************/
function () payable public {
    buy();
}

/// @notice Buy tokens from contract by sending ether