contract VampTokenSale is Ownable {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    IERC20 public usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);
    address public collector = 0x45a6b8BdfC1FAa745720165e0B172A3D6D4EC897;
    string public name = "VAMP Presale";

    IERC20 public VAMP = IERC20(0xb2C822a1b923E06Dbd193d2cFc7ad15388EA09DD);
    address public beneficiary;

    uint256 public hardCap;
    uint256 public softCap;
    uint256 public tokensPerUSDT;
    uint256 public purchaseLimitStageOne = 500 * 1e6;
    uint256 public purchaseLimitStageTwo = 2000 * 1e6;
    uint256 public purchaseLimitStageThree = 10000 * 1e6;

    uint256 public tokensSold = 0;
    uint256 public usdtRaised = 0;
    uint256 public investorCount = 0;
    uint256 public weiRefunded = 0;
    uint256 public minAmount = 1 * 1e6;
    uint256 public maxAmount = 10000 * 1e6;

    uint256 public startTime;
    uint256 public endTime;
    uint256 public stageOne = 2 hours;
    uint256 public stageTwo = 4 hours;
    uint256 public timeHardCapReached;

    bool public softCapReached = false;
    bool public crowdsaleFinished = false;
   // address[] public whitelistAddress;
    mapping(address => uint256) sold;
    mapping(address => uint256) whitelistAmount;
    mapping(address => bool) whitelistedAddress;
    mapping(address => uint256) tokensAlreadyBought;

    event GoalReached(uint256 amountRaised);
    event HardCapReached(uint256 hardcap);
    event NewContribution(
        address indexed holder,
        uint256 tokenAmount,
        uint256 etherAmount
    );
    event Refunded(address indexed holder, uint256 amount);

    modifier onlyAfter(uint256 time) {
        require(now >= time);
        _;
    }

    modifier onlyBefore(uint256 time) {
        require(now <= time);
        _;
    }

      modifier claimEnabled() {
        require(block.timestamp.add(1 hours) >= timeHardCapReached);
        _;
    }

    constructor ( // in token-wei. i.e. number of presale tokens * 10^18
        uint256 _startTime // start time (unix time, in seconds since 1970-01-01)
       // address[] memory whitelistAddresses // presale duration in hours
    ) public {
        hardCap = 550000 * 1e6;
        tokensPerUSDT = 10000000000000;
        startTime = _startTime;
        endTime = _startTime + 48 hours;
        timeHardCapReached = endTime;
       // whitelistAddress = whitelistAddresses;
    }

    function() payable external {
        revert("not purchased by eth");
        // doPurchase(msg.sender);
    }
    function canClaim() public view returns (bool){
         if(block.timestamp.add(1 hours) >= timeHardCapReached){
             return true;
         } else {
             return false;
         }
    }

  /*  function refund() external onlyAfter(endTime) {
        require(!softCapReached);
        uint256 balance = sold[msg.sender];
        require(balance > 0);
        uint256 refund = balance / tokensPerUSDT;
        msg.sender.transfer(refund);
        delete sold[msg.sender];
        weiRefunded = weiRefunded.add(refund);
        token.refundPresale(msg.sender, balance);
        Refunded(msg.sender, refund);
    }*/
    
    function addWhiteListedAddresses(address[] memory _addresses) public onlyOwner {
        require(_addresses.length > 0);
        for (uint i = 0; i < _addresses.length; i++) {
         whitelistedAddress[_addresses[i]] = true;
    }
    }
    
    function isWhitelisted(address _address) public view returns (bool) {
        if(whitelistedAddress[_address]) {
            return true;
        } else {
            return false;
        }
    }
    function simulatebuy(uint256 amount) public view returns (uint256) {
          uint256 tokens = amount * tokensPerUSDT;
          return tokens;
    }
    
    function tokensBought(address _address) public view returns (uint256) {
        return tokensAlreadyBought[_address];
    }
    
    function tokensAlreadySold() public view returns (uint256) {
        return tokensSold;
    }
    
    function raisedUSDT() public view returns (uint256) {
        return usdtRaised;
    }
    function usdtDeposited(address _address) public view returns (uint256) {
        return whitelistAmount[_address].add(sold[_address]);
    }
    
    function getStage() public view returns (uint256) {
         if (block.timestamp <= startTime.add(stageOne)) {
             return 1;
         } else if(block.timestamp >= startTime.add(stageOne) &&
            block.timestamp <= startTime.add(stageTwo)) {
                return 2;
            } else {
                return 3;
            }
    }
    

    function withdrawTokens() public onlyOwner onlyAfter(timeHardCapReached) {
        VAMP.safeTransfer(collector, VAMP.balanceOf(address(this)));
    }

    function claimTokens() public claimEnabled() {
        
        if(tokensAlreadyBought[msg.sender] > 0){
        VAMP.safeTransfer(msg.sender,tokensAlreadyBought[msg.sender]);
        tokensAlreadyBought[msg.sender]= 0;
        } else {
            revert("No tokens to claim");
        }
       
    }

    function purchase(uint256 amount) public {
        require(amount > minAmount,"Must be more than minumum amount 1USDT");
        require(amount <= maxAmount,"Must be smaller than max amount 10k usdt");
      doPurchase(amount);
    }
     function doPurchase(uint256 amount)
        private
        onlyAfter(startTime)
        onlyBefore(endTime)
    {
        assert(crowdsaleFinished == false);

        require(usdtRaised.add(amount) <= hardCap,"cant deposit without triggering hardcap");
        if (block.timestamp <= startTime.add(stageOne) && isWhitelisted(msg.sender)) {
            //first 2 hours
            uint256 tokens = amount * tokensPerUSDT;
            require(
                amount <= purchaseLimitStageOne,
                "Over purchase limit in stage one"
            );
            require(
                whitelistAmount[msg.sender].add(amount) <= purchaseLimitStageOne,
                "can't purchase more than allowed amount stage one"
            );
            usdt.safeTransferFrom(msg.sender, collector, amount);
            whitelistAmount[msg.sender] = whitelistAmount[msg.sender].add(
                amount
            );
            usdtRaised = usdtRaised.add(amount);
            tokensSold = tokensSold.add(tokens);
            tokensAlreadyBought[msg.sender] = tokensAlreadyBought[msg.sender].add(tokens);
        } else if (
            block.timestamp >= startTime.add(stageOne) &&
            block.timestamp <= startTime.add(stageTwo)
        ) {
            //first 2 - 4 hours

            uint256 tokens = amount * tokensPerUSDT;
            require(
                amount <= purchaseLimitStageTwo,
                "Over purchase limit in stage two"
            );
            require(
                sold[msg.sender].add(amount) <=
                    purchaseLimitStageTwo,
                "can't purchase more than allowed amount stage two"
            );
            sold[msg.sender] = sold[msg.sender].add(amount);
            usdt.safeTransferFrom(msg.sender, collector, amount);
            usdtRaised = usdtRaised.add(amount);
            tokensSold = tokensSold.add(tokens);
            tokensAlreadyBought[msg.sender] = tokensAlreadyBought[msg.sender].add(tokens);
        } else if (block.timestamp > startTime.add(stageTwo)) {
            //4 - 48 hours
             uint256 tokens = amount * tokensPerUSDT;
             require(
                amount <= purchaseLimitStageThree,
                "Over purchase limit in stage three"
            );
               require(
                sold[msg.sender].add(amount) <=
                    purchaseLimitStageThree,
                "can't purchase more than allowed amount stage three"
            );
            sold[msg.sender] = sold[msg.sender].add(amount);
            usdt.safeTransferFrom(msg.sender, collector, amount);
            usdtRaised = usdtRaised.add(amount);
            tokensSold = tokensSold.add(tokens);
            tokensAlreadyBought[msg.sender] = tokensAlreadyBought[msg.sender].add(tokens);
        }
         if (usdtRaised == hardCap) {
          timeHardCapReached = block.timestamp;
          crowdsaleFinished = true;
          emit HardCapReached(timeHardCapReached);
        }

    }
}
function addWhiteListedAddresses(address[] memory _addresses) public onlyOwner {
        require(_addresses.length > 0);
        for (uint i = 0; i < _addresses.length; i++) {
         whitelistedAddress[_addresses[i]] = true;
    }
    }
/*  function refund() external onlyAfter(endTime) {
 require(!softCapReached);
 uint256 balance = sold[msg.sender];
 require(balance > 0);
 uint256 refund = balance / tokensPerUSDT;
 msg.sender.transfer(refund);
 delete sold[msg.sender];
 weiRefunded = weiRefunded.add(refund);
 token.refundPresale(msg.sender, balance);
 Refunded(msg.sender, refund);
 }*/