export interface ProvisionDistribution {
  total: bigint
  payer: bigint
  receiver: bigint
}

export interface LiquidityQuote {
  totalFutureProvisionNotional: ProvisionDistribution
  totalFutureProvisionPayerDv01: bigint
  totalFutureProvisionReceiverDv01: bigint
  newMarginThreshold: bigint
  newProvisionDistribution: ProvisionDistribution
  newProvisionNotionalDv01: bigint
  marketPortfolio: MarketPortfolio
}

export interface VAMMParams {
  lowerBoundRate: bigint
  currentFutureRate: bigint
  upperBoundRate: bigint
  intervalLength: bigint
  intervalsCount: number
}

export interface FutureInfo {
  id: string
  marketId: string
  termStart: bigint
  termLength: bigint
  vAMMParams: VAMMParams
  totalLiquidityNotional: bigint
  openInterest: bigint
}

export enum RiskDirection {
  RECEIVER = 0,
  PAYER = 1
}

export enum LiquidityOperation {
  PROVIDE = 0,
  REMOVE = 1
}

export enum IRateMathType {
  LINEAR = 0,
  COMPOUNDING = 1
}

export interface MarketDescriptor {
  id: string
  sourceName: string
  instrumentName: string
  tag: string
  version: number
  underlying: string
  underlyingName: string
  underlyingDecimals: bigint
  underlyingIsWrappedNativeToken: boolean
  rateMathType: IRateMathType
}

export interface MarketInfo {
  descriptor: MarketDescriptor
  futures: FutureInfo[]
  openInterest: bigint
  totalLiquidityNotional: bigint
}

export interface FixedAndFloatTokensPair {
  fixedTokenAmount: bigint
  floatTokenAmount: bigint
}

export interface TradeInfo {
  notional: bigint
  direction: RiskDirection
  tokensPair: FixedAndFloatTokensPair
  marketRateBefore: bigint
  marketRateAfter: bigint
  tradeRate: bigint
  lpFee: bigint
  protocolFee: bigint
  floatIndex: bigint
}

export interface OneDirectionTradeQuote {
  tradeInfo: TradeInfo
  totalFutureOpenPositionNotional: bigint
  totalFutureOpenPositionDv01: bigint
  newMargin: Margin
  newMarginThreshold: bigint
  tradeNotionalDv01: bigint
}

export interface TradeQuote {
  insufficientLiquidityForPayer: boolean
  insufficientLiquidityForReceiver: boolean
  exceededTradeRateImpactLimitForPayer: boolean
  exceededTradeRateImpactLimitForReceiver: boolean
  exceededTradeNotionalLimitForPayer: boolean
  exceededTradeNotionalLimitForReceiver: boolean
  exceededMarketRateImpactLimitForPayer: boolean
  exceededMarketRateImpactLimitForReceiver: boolean
  payerQuote: OneDirectionTradeQuote
  receiverQuote: OneDirectionTradeQuote
  marketPortfolio: MarketPortfolio
}

export interface ProfitAndLoss {
  netFutureValue: bigint
  accruedLPFee: bigint
  incurredFee: bigint
}

export interface Margin {
  collateral: bigint
  profitAndLoss: ProfitAndLoss
}

export interface MarginState {
  margin: Margin
  initialMarginThreshold: bigint
  liquidationMarginThreshold: bigint
  lpMarginThreshold: bigint
  dv01: bigint
  riskDirection: RiskDirection
}

export interface FutureOpenPosition {
  futureId: string
  tokensPair: FixedAndFloatTokensPair
  notional: bigint
  profitAndLoss: ProfitAndLoss
  requiredMargin: bigint
  dv01: bigint
  riskDirection: RiskDirection
}

export interface RateBounds {
  lower: bigint
  upper: bigint
}

export interface ProvisionInfo {
  bounds: RateBounds
  notional: ProvisionDistribution
  requiredMargin: bigint
  payerDv01: bigint
  receiverDv01: bigint
}

export interface MakerFutureProvisions {
  futureId: string
  provisions: ProvisionInfo[]
}

export interface MarketPortfolio {
  descriptor: MarketDescriptor
  marginState: MarginState
  futures: FutureInfo[]
  futureOpenPositions: FutureOpenPosition[]
  futureMakerProvisions: MakerFutureProvisions[]
}

export interface OraclePackage {
  indexValue: string
  marketId: string
  signature: string
  timestamp: number
}

export interface MarketOraclePackages {
  marketId: string
  packages: OraclePackage[]
}

export interface IntervalLiquidity {
  notional: bigint
  bounds: RateBounds
}

export interface LiquidityDistribution {
  provisionDistribution: ProvisionDistribution
  currentFutureRate: bigint
  intervalLiquidity: IntervalLiquidity[]
}

export interface MakerLiquidityDistribution {
  currentFutureRate: bigint
  intervalLiquidity: IntervalLiquidity[]
}

export enum UserRole {
  PROTOCOL_USER = 'PROTOCOL_USER',
  PROTOCOL_USER_MANAGER = 'PROTOCOL_USER_MANAGER',
  ISSUER = 'ISSUER',
  ORACLE_SIGNER = 'ORACLE_SIGNER',
  EMERGENCY_MANAGER = 'EMERGENCY_MANAGER',
  RISK_MANAGER = 'RISK_MANAGER',
  REWARD_MANAGER = 'REWARD_MANAGER',
  MATURITY_COURIER = 'MATURITY_COURIER',
  LIQUIDATOR = 'LIQUIDATOR',
  SUPER_LIQUIDATOR = 'SUPER_LIQUIDATOR'
}

export const GrantUserRoleMethodMap = {
  [UserRole.PROTOCOL_USER]: 'grantProtocolUser',
  [UserRole.ISSUER]: 'grantIssuer',
  [UserRole.ORACLE_SIGNER]: 'grantOracleSigner',
  [UserRole.EMERGENCY_MANAGER]: 'grantEmergencyManager',
  [UserRole.RISK_MANAGER]: 'grantRiskManager',
  [UserRole.REWARD_MANAGER]: 'grantRewardManager',
  [UserRole.PROTOCOL_USER_MANAGER]: 'grantProtocolUserManager',
  [UserRole.MATURITY_COURIER]: 'grantMaturityCourier',
  [UserRole.LIQUIDATOR]: 'grantLiquidator',
  [UserRole.SUPER_LIQUIDATOR]: 'grantSuperLiquidator',
}

export const RevokeUserRoleMethodMap = {
  [UserRole.PROTOCOL_USER]: 'revokeProtocolUser',
  [UserRole.ISSUER]: 'revokeIssuer',
  [UserRole.ORACLE_SIGNER]: 'revokeOracleSigner',
  [UserRole.EMERGENCY_MANAGER]: 'revokeEmergencyManager',
  [UserRole.RISK_MANAGER]: 'revokeRiskManager',
  [UserRole.REWARD_MANAGER]: 'revokeRewardManager',
  [UserRole.PROTOCOL_USER_MANAGER]: 'revokeProtocolUserManager',
  [UserRole.MATURITY_COURIER]: 'revokeMaturityCourier',
  [UserRole.LIQUIDATOR]: 'revokeLiquidator',
  [UserRole.SUPER_LIQUIDATOR]: 'revokeSuperLiquidator',
}
