// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

interface IDODOPMMSwapPool {
    function _BASE_TOKEN_() external view returns (address);
    function _QUOTE_TOKEN_() external view returns (address);
    function sellBase(address to) external returns (uint256 receiveQuoteAmount);
    function sellQuote(address to) external returns (uint256 receiveBaseAmount);
}

/**
 * @notice Minimal public adapter for DVM-style Chain 138 PMM pools.
 * @dev Keeps the atomic-swap dapp's existing swapExactIn surface while using
 *      the pool execution selectors exposed by the Chain 138 PMM pools.
 */
contract DODOPMMSwapAdapter is ReentrancyGuard {
    using SafeERC20 for IERC20;

    event SwapExecuted(
        address indexed pool,
        address indexed tokenIn,
        address indexed tokenOut,
        uint256 amountIn,
        uint256 amountOut,
        address trader
    );

    function swapExactIn(
        address pool,
        address tokenIn,
        uint256 amountIn,
        uint256 minAmountOut
    ) external nonReentrant returns (uint256 amountOut) {
        require(pool != address(0), "DODOPMMSwapAdapter: zero pool");
        require(tokenIn != address(0), "DODOPMMSwapAdapter: zero token");
        require(amountIn > 0, "DODOPMMSwapAdapter: zero amount");

        address baseToken = IDODOPMMSwapPool(pool)._BASE_TOKEN_();
        address quoteToken = IDODOPMMSwapPool(pool)._QUOTE_TOKEN_();
        address tokenOut;

        if (tokenIn == baseToken) {
            tokenOut = quoteToken;
            IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);
            amountOut = IDODOPMMSwapPool(pool).sellBase(msg.sender);
        } else if (tokenIn == quoteToken) {
            tokenOut = baseToken;
            IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);
            amountOut = IDODOPMMSwapPool(pool).sellQuote(msg.sender);
        } else {
            revert("DODOPMMSwapAdapter: token not in pool");
        }

        require(amountOut >= minAmountOut, "DODOPMMSwapAdapter: insufficient output");
        emit SwapExecuted(pool, tokenIn, tokenOut, amountIn, amountOut, msg.sender);
    }
}
