// File: contracts/PaymentEthereum.sol



// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.0;

interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

interface IUniswapV3SwapCallback {
    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata data
    ) external;
}

interface ISwapRouter is IUniswapV3SwapCallback {
    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96;
    }
    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);

    struct ExactInputParams {
        bytes path;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
    }
    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);

    struct ExactOutputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 deadline;
        uint256 amountOut;
        uint256 amountInMaximum;
        uint160 sqrtPriceLimitX96;
    }
    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);

    struct ExactOutputParams {
        bytes path;
        address recipient;
        uint256 deadline;
        uint256 amountOut;
        uint256 amountInMaximum;
    }
    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}


contract PaymentEthereum
{
    ISwapRouter public swapRouter;

    constructor(
        address _swapRouter
    ) {
        swapRouter = ISwapRouter(_swapRouter);
    }

    function performPaymentWithToken(
        address _tokenIn,
        address _tokenOut,
        uint256 _amount,
        bytes calldata burnPath,
        address treasuryAddress
    ) external {
        
        IERC20 token = IERC20(_tokenIn);
        token.transferFrom(msg.sender, address(this), _amount);
        token.approve(address(swapRouter), _amount);

        ISwapRouter.ExactInputParams memory params =
            ISwapRouter.ExactInputParams({
                path: burnPath,
                recipient: address(this),
                deadline: block.timestamp + 30000,
                amountIn: _amount,
                amountOutMinimum: 0
            });
            
        uint256 swapAmount = swapRouter.exactInput(params);
        
        IERC20 _usdcToken = IERC20(_tokenOut);
        _usdcToken.transfer(treasuryAddress, swapAmount);
            
    }

    function performPaymentWithNative(
        address _tokenOut,
        bytes calldata burnPath,
        address treasuryAddress
    ) external payable {
        ISwapRouter.ExactInputParams memory params =
        ISwapRouter.ExactInputParams({
            path: burnPath,
            recipient: address(this),
            deadline: block.timestamp + 30000,
            amountIn: msg.value,
            amountOutMinimum: 0
        });
        uint256 swapAmount = swapRouter.exactInput{value: msg.value}(params);
        IERC20 _usdcToken = IERC20(_tokenOut);
        _usdcToken.transfer(treasuryAddress, swapAmount);
    }
}