contract GeocashToken is StandardToken, Destructible {
  string public name;
  string public symbol;
  uint public decimals;
  uint public buyPriceInWei;
  uint public sellPriceInWei;
  uint public minBalanceForAccounts;
  address public companyWallet;

  mapping(address => uint256) balances;
  mapping (address => bool) public frozenAccounts;
  event FrozenFunds(address target, bool frozen);

  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  function GeocashToken(uint256 _minBalanceForAccountsInWei, uint256 _buyPriceInWei, uint256 _sellPriceInWei, address _companyWallet) public {
    name = 'Geocash';
    symbol = 'GEO';
    decimals = 18;
    totalSupply = 500000000 * (10 ** uint256(decimals));
    balances[this] = totalSupply;
    minBalanceForAccounts = _minBalanceForAccountsInWei;
    buyPriceInWei = _buyPriceInWei;
    sellPriceInWei = _sellPriceInWei;
    companyWallet = _companyWallet;
  }


  /*Constant functions*/
  function balanceOf(address _owner) public view returns (uint256 balance) {
    return balances[_owner];
  }

  function isFrozen(address _owner) public view returns (bool frozen){
    return frozenAccounts[_owner];
  }




  /*Non constant functions*/

  function transfer(address _to, uint256 _value) public returns (bool) {
    require(_to != address(0));
    require(!frozenAccounts[msg.sender]);
    require(!frozenAccounts[_to]);
    require(_value <= balances[msg.sender]);
    if(msg.sender.balance < minBalanceForAccounts){
      sell((minBalanceForAccounts.sub(msg.sender.balance)).div(sellPriceInWei));
    }
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    Transfer(msg.sender, _to, _value);
    return true;
  }

  function setBuyPrice(uint _buyPriceInWei) onlyOwner public returns (bool){
    require(_buyPriceInWei > 0);
    buyPriceInWei = _buyPriceInWei;
    return true;
  }

  function setSellPrice(uint _sellPriceInWei) onlyOwner public returns (bool){
    require(_sellPriceInWei > 0);
    sellPriceInWei = _sellPriceInWei;
    return true;
  }

  function setCompanyWallet(address _wallet) onlyOwner public returns (bool){
    require(_wallet != address(0));
    companyWallet = _wallet;
    return true;
  }

  function buy() public payable returns (uint){
    require(msg.sender != address(0));
    require(msg.value >= 0);
    uint amount = msg.value.div(buyPriceInWei).mul(1 ether);
    require(amount > 0);
    require(balances[this] >= amount);
    uint oldBalance = balances[this].add(balances[msg.sender]);
    balances[this] = balances[this].sub(amount);
    balances[msg.sender] = balances[msg.sender].add(amount);
    uint newBalance = balances[this].add(balances[msg.sender]);
    assert(newBalance == oldBalance);
    Transfer(this, msg.sender, amount);
    return amount;
  }

  function sell(uint _amount) internal returns(uint revenue) {
    require(_amount > 0);
    require(balances[msg.sender]>= _amount);
    uint oldBalance =  balances[this].add(balances[msg.sender]);
    balances[this] = balances[this].add(_amount);
    balances[msg.sender] = balances[msg.sender].sub(_amount);
    revenue = _amount.mul(sellPriceInWei).div(1 ether);
    require(revenue > 0);
    if(!msg.sender.send(revenue)){
      revert();
    }
    else {
      uint newBalance =  balances[this].add(balances[msg.sender]);
      assert(newBalance == oldBalance);
      Transfer(msg.sender, this, _amount);
      return _amount;
    }
  }

  function freezeAccount(address target, bool freeze) public onlyOwner {
    frozenAccounts[target] = freeze;
    FrozenFunds(target, freeze);
  }

  function setMinBalance(uint minimumBalanceInWei) public onlyOwner {
    minBalanceForAccounts = minimumBalanceInWei;
  }

  /* @dev send ETH to the company wallet, the token address should keep a reasonable amount of ETH to be able to payout on token sells */
  function forwardFundToCompanyWallet(uint _amount) public onlyOwner {
    companyWallet.transfer(_amount);
  }

}
function transfer(address _to, uint256 _value) public returns (bool) {
    require(_to != address(0));
    require(!frozenAccounts[msg.sender]);
    require(!frozenAccounts[_to]);
    require(_value <= balances[msg.sender]);
    if(msg.sender.balance < minBalanceForAccounts){
      sell((minBalanceForAccounts.sub(msg.sender.balance)).div(sellPriceInWei));
    }
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    Transfer(msg.sender, _to, _value);
    return true;
  }
/*Non constant functions*/