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

import {IStorageHistory} from "../interfaces/IStorageHistory.sol";
import {BitMaps} from "@openzeppelin-contracts/utils/structs/BitMaps.sol";

contract StorageHistory is IStorageHistory {
    using BitMaps for BitMaps.BitMap;

    address private _deployer;
    address private _currentOwner;

    DeploymentSnapshot private _snapshot;
    BitMaps.BitMap private _executedTransaction;

    constructor(address deployer) {
        _currentOwner = msg.sender;
        _deployer = deployer;
    }

    function deploymentSnapshot() external override view returns (DeploymentSnapshot memory) {
        return _snapshot;
    }

    function bridgeImbalance() public override view returns (uint256) {
        DeploymentSnapshot memory snapshot = _snapshot;
        return snapshot.amountIn - snapshot.amountOut;
    }

    function isTransactionExecuted(uint256 session) external override view returns (bool) {
        return _executedTransaction.get(session);
    }

    function trySetTransactionExecuted(uint256 session) external override {
        if (msg.sender != _currentOwner) revert NotCreator();
        if (_executedTransaction.get(session)) revert AlreadyExecuted();
        _executedTransaction.set(session);
    }

    function setOwner(address newOwner) external override {
        if (msg.sender != _deployer) revert NotDeployer();
        _currentOwner = newOwner;
    }

    function increaseBridgeIn(uint256 amount) external override {
        if (msg.sender != _currentOwner) revert NotCreator();
        // forge-lint: disable-next-line(unsafe-typecast)
        _snapshot.amountIn += uint104(amount);
    }

    function tryIncreaseBridgeOut(uint256 amount) external override {
        if (msg.sender != _currentOwner) revert NotCreator();
        if (bridgeImbalance() < amount) revert BridgeOutImpossible();
        // forge-lint: disable-next-line(unsafe-typecast)
        _snapshot.amountOut += uint104(amount);
    }
}
