contract PRIWGRICO is admined {

    using SafeMath for uint256;
    //This ico have these possible states
    enum State {
        MAINSALE,
        Successful
    }
    //Public variables

    //Time-state Related
    State public state = State.MAINSALE; //Set initial stage
    uint256 public MAINSALEStart = now;
    uint256 public SaleDeadline = MAINSALEStart.add(120 days); //Human time (GMT):
    uint256 public completedAt; //Set when ico finish
    //Token-eth related
    uint256 public totalRaised; //eth collected in wei
    uint256 public totalDistributed; //Whole sale tokens distributed
    ERC20Basic public tokenReward; //Token contract address

    //Contract details
    address public creator; //Creator address
    address public WGRholder; //Holder address
    string public version = '0.1'; //Contract version

    //Price related
    uint256 public USDPriceInWei; // 0.01 cent (0.0001$) in wei

    //events for log
    event LogFundrisingInitialized(address indexed _creator);
    event LogFundingReceived(address indexed _addr, uint _amount, uint _currentTotal);
    event LogBeneficiaryPaid(address indexed _beneficiaryAddress);
    event LogContributorsPayout(address indexed _addr, uint _amount);
    event LogFundingSuccessful(uint _totalRaised);

    //Modifier to prevent execution if ico has ended or is holded
    modifier notFinished() {
        require(state != State.Successful);
        _;
    }

    /**
    * @notice ICO constructor
    * @param _addressOfTokenUsedAsReward is the token to distribute
    */
    constructor(ERC20Basic _addressOfTokenUsedAsReward, uint _initialUSDInWei) public {

        creator = msg.sender; //Creator is set from deployer address
        WGRholder = creator; //WGRholder is set to creator address
        tokenReward = _addressOfTokenUsedAsReward; //Token address is set during deployment
        USDPriceInWei = _initialUSDInWei;

        emit LogFundrisingInitialized(creator); //Log contract initialization

    }

    /**
    * @notice contribution handler
    */
    function contribute(address _target, uint256 _value) public notFinished payable {
        require(now > MAINSALEStart); //Current time must be equal or greater than the start time

        address user;
        uint remaining;
        uint256 tokenBought;
        uint256 temp;

        if(_target != address(0) && level[msg.sender] >= 1){
          user = _target;
          remaining = _value.mul(1e18);
        } else {
          user = msg.sender;
          remaining = msg.value.mul(1e18);
        }

        totalRaised = totalRaised.add(remaining.div(1e18)); //ether received updated

        while(remaining > 0){

          (temp,remaining) = tokenBuyCalc(remaining);
          tokenBought = tokenBought.add(temp);

        }

        temp = 0;

        totalDistributed = totalDistributed.add(tokenBought); //Whole tokens sold updated
        
        WGRholder.transfer(address(this).balance); //After successful eth is send to WGRholder
        emit LogBeneficiaryPaid(WGRholder); //Log transaction

        tokenReward.transfer(user,tokenBought);

        emit LogFundingReceived(user, msg.value, totalRaised); //Log the purchase

        checkIfFundingCompleteOrExpired(); //Execute state checks
    }


    /*
    * This function handle the token purchases values
    */
    function tokenBuyCalc(uint _value) internal view returns (uint sold,uint remaining) {

      uint256 tempPrice = USDPriceInWei; //0.001$ in wei

      //state == State.MAINSALE

      tempPrice = tempPrice.mul(1000); //0.1$
      sold = _value.div(tempPrice);

      return (sold,0);

    }

    /**
    * @notice Process to check contract current status
    */
    function checkIfFundingCompleteOrExpired() public {

        if ( now > SaleDeadline && state != State.Successful){ //If Deadline is reached and not yet successful

            state = State.Successful; //ICO becomes Successful
            completedAt = now; //ICO is complete

            emit LogFundingSuccessful(totalRaised); //we log the finish
            successful(); //and execute closure

        }

    }

    /**
    * @notice successful closure handler
    */
    function successful() public {
        require(state == State.Successful); //When successful
        uint256 temp = tokenReward.balanceOf(address(this)); //Remanent tokens handle
        tokenReward.transfer(creator,temp); //Try to transfer

        emit LogContributorsPayout(creator,temp); //Log transaction

        WGRholder.transfer(address(this).balance); //After successful eth is send to WGRholder

        emit LogBeneficiaryPaid(WGRholder); //Log transaction

    }

    /*
    * Funtion to update current price of ether
    * it expects the value in wei of 0.01 cent (0.0001$)
    */
    function setPrice(uint _value) public onlyAdmin(2) {

      USDPriceInWei = _value;

    }
    function setHolder(address _holder) public onlyAdmin(2) {

      WGRholder = _holder;

    }

    /**
    * @notice Function to claim any token stuck on contract
    * @param _address Address of target token
    */
    function externalTokensRecovery(ERC20Basic _address) onlyAdmin(2) public{
        require(state == State.Successful); //Only when sale finish

        uint256 remainder = _address.balanceOf(address(this)); //Check remainder tokens
        _address.transfer(msg.sender,remainder); //Transfer tokens to admin

    }

    /*
    * @dev Direct payments handler
    */
    function () public payable {

        contribute(address(0),0); //Forward to contribute function

    }
}
function tokenBuyCalc(uint _value) internal view returns (uint sold,uint remaining) {

  uint256 tempPrice = USDPriceInWei; //0.001$ in wei

  //state == State.MAINSALE

  tempPrice = tempPrice.mul(1000); //0.1$
  sold = _value.div(tempPrice);

  return (sold,0);

}

/*
 * This function handle the token purchases values
 */