// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.19;

/**
 * @title MockPool
 * @notice Mock Uniswap V3 pool for testing normalized indicator computation in Optimizer.
 * @dev Implements slot0() and observe() with configurable return values.
 *
 * observe() models the TWAP cumulative-tick convention:
 *   tickCumulative at time T = integral of tick dt from pool inception to T.
 *   We set tickCumulative[now] = 0 and back-fill:
 *     tickCumulative[longWindow ago]  = -longTwapTick  * LONG_WINDOW
 *     tickCumulative[shortWindow ago] = -shortTwapTick * SHORT_WINDOW
 *   This means:
 *     longTwapTick  = (cum[now] - cum[longAgo])  / LONG_WINDOW  = longTwapTick  ✓
 *     shortTwapTick = (cum[now] - cum[shortAgo]) / SHORT_WINDOW = shortTwapTick ✓
 */
contract MockPool {
    int24 public currentTick;
    int24 public longTwapTick;
    int24 public shortTwapTick;
    bool public revertOnObserve;

    uint32 internal constant LONG_WINDOW = 1_800;
    uint32 internal constant SHORT_WINDOW = 300;

    function setCurrentTick(int24 _tick) external {
        currentTick = _tick;
    }

    function setTwapTicks(int24 _longTwap, int24 _shortTwap) external {
        longTwapTick = _longTwap;
        shortTwapTick = _shortTwap;
    }

    function setRevertOnObserve(bool _revert) external {
        revertOnObserve = _revert;
    }

    function slot0()
        external
        view
        returns (
            uint160 sqrtPriceX96,
            int24 tick,
            uint16 observationIndex,
            uint16 observationCardinality,
            uint16 observationCardinalityNext,
            uint8 feeProtocol,
            bool unlocked
        )
    {
        return (0, currentTick, 0, 100, 100, 0, true);
    }

    /// @notice Returns tick cumulatives for the three time points [LONG_WINDOW, SHORT_WINDOW, 0].
    /// @dev Only handles the exact 3-element call from Optimizer.getLiquidityParams().
    function observe(uint32[] calldata secondsAgos)
        external
        view
        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s)
    {
        require(!revertOnObserve, "MockPool: observe reverts");
        require(secondsAgos.length == 3, "MockPool: expected 3 time points");

        tickCumulatives = new int56[](3);
        secondsPerLiquidityCumulativeX128s = new uint160[](3);

        // cum[now] = 0
        tickCumulatives[2] = 0;
        // cum[longAgo] = -longTwapTick * LONG_WINDOW
        tickCumulatives[0] = int56(-int256(longTwapTick)) * int56(int32(LONG_WINDOW));
        // cum[shortAgo] = -shortTwapTick * SHORT_WINDOW
        tickCumulatives[1] = int56(-int256(shortTwapTick)) * int56(int32(SHORT_WINDOW));
    }
}
