contract NftSale is Ownable {

	uint private _totalShares;
	mapping(address => uint) private _shares;
	address[] private _payees;

	uint public constant MAX_UNITS_PER_TRANSACTION = 5;
	uint public constant MAX_NFT_TO_SELL = 1550;
	uint public constant SALE_PRICE = 0.08 ether;
	uint public constant START_TIME = 1647186249;
	
	INFT public nft;
	uint public tokensSold;

	constructor(address _nftAddress, address[] memory payees_, uint[] memory shares_) {
		require(payees_.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
        require(payees_.length > 0, "PaymentSplitter: no payees");

		nft = INFT(_nftAddress);
		for (uint i = 0; i < payees_.length; i++) {
            _addPayee(payees_[i], shares_[i]);
        }
	}
	
	/*
     * @dev Add a new payee to the contract.
     * @param account_ The address of the payee to add.
     * @param shares_ The number of shares owned by the payee.
     */
    function _addPayee(address account_, uint shares_) private {
        require(account_ != address(0), "PaymentSplitter: account is the zero address");
        require(shares_ > 0, "PaymentSplitter: shares are 0");
        require(_shares[account_] == 0, "PaymentSplitter: account already has shares");

        _payees.push(account_);
        _shares[account_] = shares_;
        _totalShares += shares_;
    }

	/*
	 * @dev function to buy tokens. 
	 * @param _amount how much tokens can be bought.
	 */
	function buyBatch(uint _amount) external payable {
		require(block.timestamp >= START_TIME, "sale is not started yet");
		require(tokensSold + _amount <= MAX_NFT_TO_SELL, "exceed sell limit");
		require(_amount > 0, "empty input");
		require(_amount <= MAX_UNITS_PER_TRANSACTION, "exceed MAX_UNITS_PER_TRANSACTION");

		uint totalPrice = SALE_PRICE * _amount;
		require(msg.value >= totalPrice, "too low value");
		if(msg.value > totalPrice) {
			//send the rest back
			(bool sent, ) = payable(msg.sender).call{value: msg.value - totalPrice}("");
        	require(sent, "Failed to send Ether");
		}
		
		tokensSold += _amount;
		nft.mintBatch(msg.sender, _amount);		
	}

    function cashOut() public onlyOwner {
        uint _balance = address(this).balance;
		for (uint i = 0; i < _payees.length; i++) {
            uint _payment = _balance * _shares[_payees[i]] / _totalShares; 
			Address.sendValue(payable(_payees[i]), _payment);
        }
    }
}
function buyBatch(uint _amount) external payable {
	require(block.timestamp >= START_TIME, "sale is not started yet");
	require(tokensSold + _amount <= MAX_NFT_TO_SELL, "exceed sell limit");
	require(_amount > 0, "empty input");
	require(_amount <= MAX_UNITS_PER_TRANSACTION, "exceed MAX_UNITS_PER_TRANSACTION");

	uint totalPrice = SALE_PRICE * _amount;
	require(msg.value >= totalPrice, "too low value");
	if(msg.value > totalPrice) {
		//send the rest back
		(bool sent, ) = payable(msg.sender).call{value: msg.value - totalPrice}("");
       	require(sent, "Failed to send Ether");
	}
		
	tokensSold += _amount;
	nft.mintBatch(msg.sender, _amount);		
}

/*
 	 * @dev function to buy tokens. 
 	 * @param _amount how much tokens can be bought.
 	 */