import { PublicKey } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@project-serum/borsh"

export interface RewardInfoFields {
  /** Reward state */
  rewardState: number
  /** Reward open time */
  openTime: BN
  /** Reward end time */
  endTime: BN
  /** Reward last update time */
  lastUpdateTime: BN
  /** Q64.64 number indicates how many tokens per second are earned per unit of liquidity. */
  emissionsPerSecondX64: BN
  /** The total amount of reward emissioned */
  rewardTotalEmissioned: BN
  /** The total amount of claimed reward */
  rewardClaimed: BN
  /** Reward token mint. */
  tokenMint: PublicKey
  /** Reward vault token account. */
  tokenVault: PublicKey
  /** The owner that has permission to set reward param */
  authority: PublicKey
  /**
   * Q64.64 number that tracks the total tokens earned per unit of liquidity since the reward
   * emissions were turned on.
   */
  rewardGrowthGlobalX64: BN
}

export interface RewardInfoJSON {
  /** Reward state */
  rewardState: number
  /** Reward open time */
  openTime: string
  /** Reward end time */
  endTime: string
  /** Reward last update time */
  lastUpdateTime: string
  /** Q64.64 number indicates how many tokens per second are earned per unit of liquidity. */
  emissionsPerSecondX64: string
  /** The total amount of reward emissioned */
  rewardTotalEmissioned: string
  /** The total amount of claimed reward */
  rewardClaimed: string
  /** Reward token mint. */
  tokenMint: string
  /** Reward vault token account. */
  tokenVault: string
  /** The owner that has permission to set reward param */
  authority: string
  /**
   * Q64.64 number that tracks the total tokens earned per unit of liquidity since the reward
   * emissions were turned on.
   */
  rewardGrowthGlobalX64: string
}

export class RewardInfo {
  /** Reward state */
  readonly rewardState: number
  /** Reward open time */
  readonly openTime: BN
  /** Reward end time */
  readonly endTime: BN
  /** Reward last update time */
  readonly lastUpdateTime: BN
  /** Q64.64 number indicates how many tokens per second are earned per unit of liquidity. */
  readonly emissionsPerSecondX64: BN
  /** The total amount of reward emissioned */
  readonly rewardTotalEmissioned: BN
  /** The total amount of claimed reward */
  readonly rewardClaimed: BN
  /** Reward token mint. */
  readonly tokenMint: PublicKey
  /** Reward vault token account. */
  readonly tokenVault: PublicKey
  /** The owner that has permission to set reward param */
  readonly authority: PublicKey
  /**
   * Q64.64 number that tracks the total tokens earned per unit of liquidity since the reward
   * emissions were turned on.
   */
  readonly rewardGrowthGlobalX64: BN

  constructor(fields: RewardInfoFields) {
    this.rewardState = fields.rewardState
    this.openTime = fields.openTime
    this.endTime = fields.endTime
    this.lastUpdateTime = fields.lastUpdateTime
    this.emissionsPerSecondX64 = fields.emissionsPerSecondX64
    this.rewardTotalEmissioned = fields.rewardTotalEmissioned
    this.rewardClaimed = fields.rewardClaimed
    this.tokenMint = fields.tokenMint
    this.tokenVault = fields.tokenVault
    this.authority = fields.authority
    this.rewardGrowthGlobalX64 = fields.rewardGrowthGlobalX64
  }

  static layout(property?: string) {
    return borsh.struct(
      [
        borsh.u8("rewardState"),
        borsh.u64("openTime"),
        borsh.u64("endTime"),
        borsh.u64("lastUpdateTime"),
        borsh.u128("emissionsPerSecondX64"),
        borsh.u64("rewardTotalEmissioned"),
        borsh.u64("rewardClaimed"),
        borsh.publicKey("tokenMint"),
        borsh.publicKey("tokenVault"),
        borsh.publicKey("authority"),
        borsh.u128("rewardGrowthGlobalX64"),
      ],
      property
    )
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  static fromDecoded(obj: any) {
    return new RewardInfo({
      rewardState: obj.rewardState,
      openTime: obj.openTime,
      endTime: obj.endTime,
      lastUpdateTime: obj.lastUpdateTime,
      emissionsPerSecondX64: obj.emissionsPerSecondX64,
      rewardTotalEmissioned: obj.rewardTotalEmissioned,
      rewardClaimed: obj.rewardClaimed,
      tokenMint: obj.tokenMint,
      tokenVault: obj.tokenVault,
      authority: obj.authority,
      rewardGrowthGlobalX64: obj.rewardGrowthGlobalX64,
    })
  }

  static toEncodable(fields: RewardInfoFields) {
    return {
      rewardState: fields.rewardState,
      openTime: fields.openTime,
      endTime: fields.endTime,
      lastUpdateTime: fields.lastUpdateTime,
      emissionsPerSecondX64: fields.emissionsPerSecondX64,
      rewardTotalEmissioned: fields.rewardTotalEmissioned,
      rewardClaimed: fields.rewardClaimed,
      tokenMint: fields.tokenMint,
      tokenVault: fields.tokenVault,
      authority: fields.authority,
      rewardGrowthGlobalX64: fields.rewardGrowthGlobalX64,
    }
  }

  toJSON(): RewardInfoJSON {
    return {
      rewardState: this.rewardState,
      openTime: this.openTime.toString(),
      endTime: this.endTime.toString(),
      lastUpdateTime: this.lastUpdateTime.toString(),
      emissionsPerSecondX64: this.emissionsPerSecondX64.toString(),
      rewardTotalEmissioned: this.rewardTotalEmissioned.toString(),
      rewardClaimed: this.rewardClaimed.toString(),
      tokenMint: this.tokenMint.toString(),
      tokenVault: this.tokenVault.toString(),
      authority: this.authority.toString(),
      rewardGrowthGlobalX64: this.rewardGrowthGlobalX64.toString(),
    }
  }

  static fromJSON(obj: RewardInfoJSON): RewardInfo {
    return new RewardInfo({
      rewardState: obj.rewardState,
      openTime: new BN(obj.openTime),
      endTime: new BN(obj.endTime),
      lastUpdateTime: new BN(obj.lastUpdateTime),
      emissionsPerSecondX64: new BN(obj.emissionsPerSecondX64),
      rewardTotalEmissioned: new BN(obj.rewardTotalEmissioned),
      rewardClaimed: new BN(obj.rewardClaimed),
      tokenMint: new PublicKey(obj.tokenMint),
      tokenVault: new PublicKey(obj.tokenVault),
      authority: new PublicKey(obj.authority),
      rewardGrowthGlobalX64: new BN(obj.rewardGrowthGlobalX64),
    })
  }

  toEncodable() {
    return RewardInfo.toEncodable(this)
  }
}
