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

import { LibHashing } from "../dispute/lib/LibHashing.sol";
import { LibPosition } from "../dispute/lib/LibPosition.sol";
import { LibClock } from "../dispute/lib/LibClock.sol";

using LibHashing for Claim global;
using LibPosition for Position global;
using LibClock for Clock global;

/// @notice A custom type for a generic hash.
type Hash is bytes32;

/// @notice A claim represents an MPT root representing the state of the fault proof program.
type Claim is bytes32;

/// @notice A claim hash represents a hash of a claim and a position within the game tree.
/// @dev Keccak hash of abi.encodePacked(Claim, Position);
type ClaimHash is bytes32;

/// @notice A bondamount represents the amount of collateral that a user has locked up in a claim.
type BondAmount is uint256;

/// @notice A dedicated timestamp type.
type Timestamp is uint64;

/// @notice A dedicated duration type.
/// @dev Unit: seconds
type Duration is uint64;

/// @notice A `GameId` represents a packed 12 byte timestamp and a 20 byte address.
/// @dev The packed layout of this type is as follows:
/// ┌────────────┬────────────────┐
/// │    Bits    │     Value      │
/// ├────────────┼────────────────┤
/// │ [0, 96)    │ Timestamp      │
/// │ [96, 256)  │ Address        │
/// └────────────┴────────────────┘
type GameId is bytes32;

/// @notice A `Clock` represents a packed `Duration` and `Timestamp`
/// @dev The packed layout of this type is as follows:
/// ┌────────────┬────────────────┐
/// │    Bits    │     Value      │
/// ├────────────┼────────────────┤
/// │ [0, 64)    │ Duration       │
/// │ [64, 128)  │ Timestamp      │
/// └────────────┴────────────────┘
type Clock is uint128;

/// @notice A `Position` represents a position of a claim within the game tree.
/// @dev This is represented as a "generalized index" where the high-order bit
/// is the level in the tree and the remaining bits is a unique bit pattern, allowing
/// a unique identifier for each node in the tree. Mathematically, it is calculated
/// as 2^{depth} + indexAtDepth.
type Position is uint128;

/// @notice A `GameType` represents the type of game being played.
type GameType is uint8;

/// @notice The current status of the dispute game.
enum GameStatus
// The game is currently in progress, and has not been resolved.
{
    IN_PROGRESS,
    // The game has concluded, and the `rootClaim` was challenged successfully.
    CHALLENGER_WINS,
    // The game has concluded, and the `rootClaim` could not be contested.
    DEFENDER_WINS
}

/// @title GameTypes
/// @notice A library that defines the IDs of games that can be played.
library GameTypes {
    /// @dev The game will use a `IDisputeGame` implementation that utilizes fault proofs.
    GameType internal constant FAULT = GameType.wrap(0);

    /// @dev The game will use a `IDisputeGame` implementation that utilizes validity proofs.
    GameType internal constant VALIDITY = GameType.wrap(1);

    /// @dev The game will use a `IDisputeGame` implementation that utilizes attestation proofs.
    GameType internal constant ATTESTATION = GameType.wrap(2);
}
