export type CustomError =
  | LOK
  | NotApproved
  | InvalidUpdateConfigFlag
  | AccountLack
  | ClosePositionErr
  | ZeroMintAmount
  | InvaildTickIndex
  | TickInvaildOrder
  | TickLowerOverflow
  | TickUpperOverflow
  | TickAndSpacingNotMatch
  | InvalidTickArray
  | InvalidTickArrayBoundary
  | SqrtPriceLimitOverflow
  | SqrtPriceX64
  | LiquiditySubValueErr
  | LiquidityAddValueErr
  | InvaildLiquidity
  | ForbidBothZeroForSupplyLiquidity
  | LiquidityInsufficient
  | TransactionTooOld
  | PriceSlippageCheck
  | TooLittleOutputReceived
  | TooMuchInputPaid
  | InvaildSwapAmountSpecified
  | InvalidInputPoolVault
  | TooSmallInputOrOutputAmount
  | NotEnoughTickArrayAccount
  | InvalidFirstTickArrayAccount
  | InvalidRewardIndex
  | FullRewardInfo
  | RewardTokenAlreadyInUse
  | ExceptPoolVaultMint
  | InvalidRewardInitParam
  | InvalidRewardDesiredAmount
  | InvalidRewardInputAccountNumber
  | InvalidRewardPeriod
  | NotApproveUpdateRewardEmissiones
  | UnInitializedRewardInfo;

export class LOK extends Error {
  static readonly code = 6000;
  readonly code = 6000;
  readonly name = 'LOK';
  readonly msg = 'LOK';

  constructor(readonly logs?: string[]) {
    super('6000: LOK');
  }
}

export class NotApproved extends Error {
  static readonly code = 6001;
  readonly code = 6001;
  readonly name = 'NotApproved';
  readonly msg = 'Not approved';

  constructor(readonly logs?: string[]) {
    super('6001: Not approved');
  }
}

export class InvalidUpdateConfigFlag extends Error {
  static readonly code = 6002;
  readonly code = 6002;
  readonly name = 'InvalidUpdateConfigFlag';
  readonly msg = 'invalid update amm config flag';

  constructor(readonly logs?: string[]) {
    super('6002: invalid update amm config flag');
  }
}

export class AccountLack extends Error {
  static readonly code = 6003;
  readonly code = 6003;
  readonly name = 'AccountLack';
  readonly msg = 'Account lack';

  constructor(readonly logs?: string[]) {
    super('6003: Account lack');
  }
}

export class ClosePositionErr extends Error {
  static readonly code = 6004;
  readonly code = 6004;
  readonly name = 'ClosePositionErr';
  readonly msg = 'Remove liquitity, collect fees owed and reward then you can close position account';

  constructor(readonly logs?: string[]) {
    super('6004: Remove liquitity, collect fees owed and reward then you can close position account');
  }
}

export class ZeroMintAmount extends Error {
  static readonly code = 6005;
  readonly code = 6005;
  readonly name = 'ZeroMintAmount';
  readonly msg = 'Minting amount should be greater than 0';

  constructor(readonly logs?: string[]) {
    super('6005: Minting amount should be greater than 0');
  }
}

export class InvaildTickIndex extends Error {
  static readonly code = 6006;
  readonly code = 6006;
  readonly name = 'InvaildTickIndex';
  readonly msg = 'Tick out of range';

  constructor(readonly logs?: string[]) {
    super('6006: Tick out of range');
  }
}

export class TickInvaildOrder extends Error {
  static readonly code = 6007;
  readonly code = 6007;
  readonly name = 'TickInvaildOrder';
  readonly msg = 'The lower tick must be below the upper tick';

  constructor(readonly logs?: string[]) {
    super('6007: The lower tick must be below the upper tick');
  }
}

export class TickLowerOverflow extends Error {
  static readonly code = 6008;
  readonly code = 6008;
  readonly name = 'TickLowerOverflow';
  readonly msg = 'The tick must be greater, or equal to the minimum tick(-221818)';

  constructor(readonly logs?: string[]) {
    super('6008: The tick must be greater, or equal to the minimum tick(-221818)');
  }
}

export class TickUpperOverflow extends Error {
  static readonly code = 6009;
  readonly code = 6009;
  readonly name = 'TickUpperOverflow';
  readonly msg = 'The tick must be lesser than, or equal to the maximum tick(221818)';

  constructor(readonly logs?: string[]) {
    super('6009: The tick must be lesser than, or equal to the maximum tick(221818)');
  }
}

export class TickAndSpacingNotMatch extends Error {
  static readonly code = 6010;
  readonly code = 6010;
  readonly name = 'TickAndSpacingNotMatch';
  readonly msg = 'tick % tick_spacing must be zero';

  constructor(readonly logs?: string[]) {
    super('6010: tick % tick_spacing must be zero');
  }
}

export class InvalidTickArray extends Error {
  static readonly code = 6011;
  readonly code = 6011;
  readonly name = 'InvalidTickArray';
  readonly msg = 'Invaild tick array account';

  constructor(readonly logs?: string[]) {
    super('6011: Invaild tick array account');
  }
}

export class InvalidTickArrayBoundary extends Error {
  static readonly code = 6012;
  readonly code = 6012;
  readonly name = 'InvalidTickArrayBoundary';
  readonly msg = 'Invaild tick array boundary';

  constructor(readonly logs?: string[]) {
    super('6012: Invaild tick array boundary');
  }
}

export class SqrtPriceLimitOverflow extends Error {
  static readonly code = 6013;
  readonly code = 6013;
  readonly name = 'SqrtPriceLimitOverflow';
  readonly msg = 'Square root price limit overflow';

  constructor(readonly logs?: string[]) {
    super('6013: Square root price limit overflow');
  }
}

export class SqrtPriceX64 extends Error {
  static readonly code = 6014;
  readonly code = 6014;
  readonly name = 'SqrtPriceX64';
  readonly msg = 'sqrt_price_x64 out of range';

  constructor(readonly logs?: string[]) {
    super('6014: sqrt_price_x64 out of range');
  }
}

export class LiquiditySubValueErr extends Error {
  static readonly code = 6015;
  readonly code = 6015;
  readonly name = 'LiquiditySubValueErr';
  readonly msg = 'Liquidity sub delta L must be smaller than before';

  constructor(readonly logs?: string[]) {
    super('6015: Liquidity sub delta L must be smaller than before');
  }
}

export class LiquidityAddValueErr extends Error {
  static readonly code = 6016;
  readonly code = 6016;
  readonly name = 'LiquidityAddValueErr';
  readonly msg = 'Liquidity add delta L must be greater, or equal to before';

  constructor(readonly logs?: string[]) {
    super('6016: Liquidity add delta L must be greater, or equal to before');
  }
}

export class InvaildLiquidity extends Error {
  static readonly code = 6017;
  readonly code = 6017;
  readonly name = 'InvaildLiquidity';
  readonly msg = 'Invaild liquidity when update position';

  constructor(readonly logs?: string[]) {
    super('6017: Invaild liquidity when update position');
  }
}

export class ForbidBothZeroForSupplyLiquidity extends Error {
  static readonly code = 6018;
  readonly code = 6018;
  readonly name = 'ForbidBothZeroForSupplyLiquidity';
  readonly msg = 'Both token amount must not be zero while supply liquidity';

  constructor(readonly logs?: string[]) {
    super('6018: Both token amount must not be zero while supply liquidity');
  }
}

export class LiquidityInsufficient extends Error {
  static readonly code = 6019;
  readonly code = 6019;
  readonly name = 'LiquidityInsufficient';
  readonly msg = 'Liquidity insufficient';

  constructor(readonly logs?: string[]) {
    super('6019: Liquidity insufficient');
  }
}

export class TransactionTooOld extends Error {
  static readonly code = 6020;
  readonly code = 6020;
  readonly name = 'TransactionTooOld';
  readonly msg = 'Transaction too old';

  constructor(readonly logs?: string[]) {
    super('6020: Transaction too old');
  }
}

export class PriceSlippageCheck extends Error {
  static readonly code = 6021;
  readonly code = 6021;
  readonly name = 'PriceSlippageCheck';
  readonly msg = 'Price slippage check';

  constructor(readonly logs?: string[]) {
    super('6021: Price slippage check');
  }
}

export class TooLittleOutputReceived extends Error {
  static readonly code = 6022;
  readonly code = 6022;
  readonly name = 'TooLittleOutputReceived';
  readonly msg = 'Too little output received';

  constructor(readonly logs?: string[]) {
    super('6022: Too little output received');
  }
}

export class TooMuchInputPaid extends Error {
  static readonly code = 6023;
  readonly code = 6023;
  readonly name = 'TooMuchInputPaid';
  readonly msg = 'Too much input paid';

  constructor(readonly logs?: string[]) {
    super('6023: Too much input paid');
  }
}

export class InvaildSwapAmountSpecified extends Error {
  static readonly code = 6024;
  readonly code = 6024;
  readonly name = 'InvaildSwapAmountSpecified';
  readonly msg = 'Swap special amount can not be zero';

  constructor(readonly logs?: string[]) {
    super('6024: Swap special amount can not be zero');
  }
}

export class InvalidInputPoolVault extends Error {
  static readonly code = 6025;
  readonly code = 6025;
  readonly name = 'InvalidInputPoolVault';
  readonly msg = 'Input pool vault is invalid';

  constructor(readonly logs?: string[]) {
    super('6025: Input pool vault is invalid');
  }
}

export class TooSmallInputOrOutputAmount extends Error {
  static readonly code = 6026;
  readonly code = 6026;
  readonly name = 'TooSmallInputOrOutputAmount';
  readonly msg = 'Swap input or output amount is too small';

  constructor(readonly logs?: string[]) {
    super('6026: Swap input or output amount is too small');
  }
}

export class NotEnoughTickArrayAccount extends Error {
  static readonly code = 6027;
  readonly code = 6027;
  readonly name = 'NotEnoughTickArrayAccount';
  readonly msg = 'Not enought tick array account';

  constructor(readonly logs?: string[]) {
    super('6027: Not enought tick array account');
  }
}

export class InvalidFirstTickArrayAccount extends Error {
  static readonly code = 6028;
  readonly code = 6028;
  readonly name = 'InvalidFirstTickArrayAccount';
  readonly msg = 'Invaild first tick array account';

  constructor(readonly logs?: string[]) {
    super('6028: Invaild first tick array account');
  }
}

export class InvalidRewardIndex extends Error {
  static readonly code = 6029;
  readonly code = 6029;
  readonly name = 'InvalidRewardIndex';
  readonly msg = 'Invalid reward index';

  constructor(readonly logs?: string[]) {
    super('6029: Invalid reward index');
  }
}

export class FullRewardInfo extends Error {
  static readonly code = 6030;
  readonly code = 6030;
  readonly name = 'FullRewardInfo';
  readonly msg = 'The init reward token reach to the max';

  constructor(readonly logs?: string[]) {
    super('6030: The init reward token reach to the max');
  }
}

export class RewardTokenAlreadyInUse extends Error {
  static readonly code = 6031;
  readonly code = 6031;
  readonly name = 'RewardTokenAlreadyInUse';
  readonly msg = 'The init reward token already in use';

  constructor(readonly logs?: string[]) {
    super('6031: The init reward token already in use');
  }
}

export class ExceptPoolVaultMint extends Error {
  static readonly code = 6032;
  readonly code = 6032;
  readonly name = 'ExceptPoolVaultMint';
  readonly msg = 'The reward tokens must contain one of pool vault mint except the last reward';

  constructor(readonly logs?: string[]) {
    super('6032: The reward tokens must contain one of pool vault mint except the last reward');
  }
}

export class InvalidRewardInitParam extends Error {
  static readonly code = 6033;
  readonly code = 6033;
  readonly name = 'InvalidRewardInitParam';
  readonly msg = 'Invalid reward init param';

  constructor(readonly logs?: string[]) {
    super('6033: Invalid reward init param');
  }
}

export class InvalidRewardDesiredAmount extends Error {
  static readonly code = 6034;
  readonly code = 6034;
  readonly name = 'InvalidRewardDesiredAmount';
  readonly msg = 'Invalid collect reward desired amount';

  constructor(readonly logs?: string[]) {
    super('6034: Invalid collect reward desired amount');
  }
}

export class InvalidRewardInputAccountNumber extends Error {
  static readonly code = 6035;
  readonly code = 6035;
  readonly name = 'InvalidRewardInputAccountNumber';
  readonly msg = 'Invalid collect reward input account number';

  constructor(readonly logs?: string[]) {
    super('6035: Invalid collect reward input account number');
  }
}

export class InvalidRewardPeriod extends Error {
  static readonly code = 6036;
  readonly code = 6036;
  readonly name = 'InvalidRewardPeriod';
  readonly msg = 'Invalid reward period';

  constructor(readonly logs?: string[]) {
    super('6036: Invalid reward period');
  }
}

export class NotApproveUpdateRewardEmissiones extends Error {
  static readonly code = 6037;
  readonly code = 6037;
  readonly name = 'NotApproveUpdateRewardEmissiones';
  readonly msg = 'Modification of emissiones is allowed within 72 hours from the end of the previous cycle';

  constructor(readonly logs?: string[]) {
    super('6037: Modification of emissiones is allowed within 72 hours from the end of the previous cycle');
  }
}

export class UnInitializedRewardInfo extends Error {
  static readonly code = 6038;
  readonly code = 6038;
  readonly name = 'UnInitializedRewardInfo';
  readonly msg = 'uninitialized reward info';

  constructor(readonly logs?: string[]) {
    super('6038: uninitialized reward info');
  }
}

export function fromCode(code: number, logs?: string[]): CustomError | null {
  switch (code) {
    case 6000:
      return new LOK(logs);
    case 6001:
      return new NotApproved(logs);
    case 6002:
      return new InvalidUpdateConfigFlag(logs);
    case 6003:
      return new AccountLack(logs);
    case 6004:
      return new ClosePositionErr(logs);
    case 6005:
      return new ZeroMintAmount(logs);
    case 6006:
      return new InvaildTickIndex(logs);
    case 6007:
      return new TickInvaildOrder(logs);
    case 6008:
      return new TickLowerOverflow(logs);
    case 6009:
      return new TickUpperOverflow(logs);
    case 6010:
      return new TickAndSpacingNotMatch(logs);
    case 6011:
      return new InvalidTickArray(logs);
    case 6012:
      return new InvalidTickArrayBoundary(logs);
    case 6013:
      return new SqrtPriceLimitOverflow(logs);
    case 6014:
      return new SqrtPriceX64(logs);
    case 6015:
      return new LiquiditySubValueErr(logs);
    case 6016:
      return new LiquidityAddValueErr(logs);
    case 6017:
      return new InvaildLiquidity(logs);
    case 6018:
      return new ForbidBothZeroForSupplyLiquidity(logs);
    case 6019:
      return new LiquidityInsufficient(logs);
    case 6020:
      return new TransactionTooOld(logs);
    case 6021:
      return new PriceSlippageCheck(logs);
    case 6022:
      return new TooLittleOutputReceived(logs);
    case 6023:
      return new TooMuchInputPaid(logs);
    case 6024:
      return new InvaildSwapAmountSpecified(logs);
    case 6025:
      return new InvalidInputPoolVault(logs);
    case 6026:
      return new TooSmallInputOrOutputAmount(logs);
    case 6027:
      return new NotEnoughTickArrayAccount(logs);
    case 6028:
      return new InvalidFirstTickArrayAccount(logs);
    case 6029:
      return new InvalidRewardIndex(logs);
    case 6030:
      return new FullRewardInfo(logs);
    case 6031:
      return new RewardTokenAlreadyInUse(logs);
    case 6032:
      return new ExceptPoolVaultMint(logs);
    case 6033:
      return new InvalidRewardInitParam(logs);
    case 6034:
      return new InvalidRewardDesiredAmount(logs);
    case 6035:
      return new InvalidRewardInputAccountNumber(logs);
    case 6036:
      return new InvalidRewardPeriod(logs);
    case 6037:
      return new NotApproveUpdateRewardEmissiones(logs);
    case 6038:
      return new UnInitializedRewardInfo(logs);
  }

  return null;
}
