package io.synor.dex;

import java.math.BigInteger;
import java.util.List;

/**
 * DEX SDK Types
 */
public class Types {

    public enum PoolType {
        CONSTANT_PRODUCT,
        STABLE,
        CONCENTRATED
    }

    public enum PositionSide {
        LONG,
        SHORT
    }

    public enum OrderType {
        MARKET,
        LIMIT,
        STOP_MARKET,
        STOP_LIMIT,
        TAKE_PROFIT,
        TAKE_PROFIT_LIMIT
    }

    public enum MarginType {
        CROSS,
        ISOLATED
    }

    public enum TimeInForce {
        GTC,
        IOC,
        FOK,
        GTD
    }

    public enum OrderStatus {
        PENDING,
        OPEN,
        PARTIALLY_FILLED,
        FILLED,
        CANCELLED,
        EXPIRED
    }
}

class Token {
    public String address;
    public String symbol;
    public String name;
    public int decimals;
    public BigInteger totalSupply;
    public Double priceUsd;
    public String logoUrl;
    public boolean verified;
}

class Pool {
    public String id;
    public Token tokenA;
    public Token tokenB;
    public Types.PoolType poolType;
    public BigInteger reserveA;
    public BigInteger reserveB;
    public double fee;
    public double tvlUsd;
    public double volume24h;
    public double apr;
    public String lpTokenAddress;
    public Integer tickSpacing;
    public String sqrtPrice;
}

class PoolFilter {
    private List<String> tokens;
    private Double minTvl;
    private Double minVolume24h;
    private Boolean verified;
    private Integer limit;
    private Integer offset;

    public List<String> getTokens() { return tokens; }
    public void setTokens(List<String> tokens) { this.tokens = tokens; }
    public Double getMinTvl() { return minTvl; }
    public void setMinTvl(Double minTvl) { this.minTvl = minTvl; }
    public Double getMinVolume24h() { return minVolume24h; }
    public void setMinVolume24h(Double minVolume24h) { this.minVolume24h = minVolume24h; }
    public Boolean getVerified() { return verified; }
    public void setVerified(Boolean verified) { this.verified = verified; }
    public Integer getLimit() { return limit; }
    public void setLimit(Integer limit) { this.limit = limit; }
    public Integer getOffset() { return offset; }
    public void setOffset(Integer offset) { this.offset = offset; }
}

class Quote {
    public String tokenIn;
    public String tokenOut;
    public BigInteger amountIn;
    public BigInteger amountOut;
    public double priceImpact;
    public List<String> route;
    public BigInteger fee;
    public BigInteger minimumReceived;
    public long expiresAt;
}

class QuoteParams {
    private String tokenIn;
    private String tokenOut;
    private BigInteger amountIn;
    private Double slippage;

    public String getTokenIn() { return tokenIn; }
    public void setTokenIn(String tokenIn) { this.tokenIn = tokenIn; }
    public String getTokenOut() { return tokenOut; }
    public void setTokenOut(String tokenOut) { this.tokenOut = tokenOut; }
    public BigInteger getAmountIn() { return amountIn; }
    public void setAmountIn(BigInteger amountIn) { this.amountIn = amountIn; }
    public Double getSlippage() { return slippage; }
    public void setSlippage(Double slippage) { this.slippage = slippage; }
}

class SwapParams {
    private String tokenIn;
    private String tokenOut;
    private BigInteger amountIn;
    private BigInteger minAmountOut;
    private Long deadline;
    private String recipient;

    public String getTokenIn() { return tokenIn; }
    public void setTokenIn(String tokenIn) { this.tokenIn = tokenIn; }
    public String getTokenOut() { return tokenOut; }
    public void setTokenOut(String tokenOut) { this.tokenOut = tokenOut; }
    public BigInteger getAmountIn() { return amountIn; }
    public void setAmountIn(BigInteger amountIn) { this.amountIn = amountIn; }
    public BigInteger getMinAmountOut() { return minAmountOut; }
    public void setMinAmountOut(BigInteger minAmountOut) { this.minAmountOut = minAmountOut; }
    public Long getDeadline() { return deadline; }
    public void setDeadline(Long deadline) { this.deadline = deadline; }
    public String getRecipient() { return recipient; }
    public void setRecipient(String recipient) { this.recipient = recipient; }
}

class SwapResult {
    public String transactionHash;
    public BigInteger amountIn;
    public BigInteger amountOut;
    public double effectivePrice;
    public BigInteger feePaid;
    public List<String> route;
}

class AddLiquidityParams {
    private String tokenA;
    private String tokenB;
    private BigInteger amountA;
    private BigInteger amountB;
    private BigInteger minAmountA;
    private BigInteger minAmountB;
    private Long deadline;

    public String getTokenA() { return tokenA; }
    public void setTokenA(String tokenA) { this.tokenA = tokenA; }
    public String getTokenB() { return tokenB; }
    public void setTokenB(String tokenB) { this.tokenB = tokenB; }
    public BigInteger getAmountA() { return amountA; }
    public void setAmountA(BigInteger amountA) { this.amountA = amountA; }
    public BigInteger getAmountB() { return amountB; }
    public void setAmountB(BigInteger amountB) { this.amountB = amountB; }
    public BigInteger getMinAmountA() { return minAmountA; }
    public void setMinAmountA(BigInteger minAmountA) { this.minAmountA = minAmountA; }
    public BigInteger getMinAmountB() { return minAmountB; }
    public void setMinAmountB(BigInteger minAmountB) { this.minAmountB = minAmountB; }
    public Long getDeadline() { return deadline; }
    public void setDeadline(Long deadline) { this.deadline = deadline; }
}

class RemoveLiquidityParams {
    private String pool;
    private BigInteger lpAmount;
    private BigInteger minAmountA;
    private BigInteger minAmountB;
    private Long deadline;

    public String getPool() { return pool; }
    public void setPool(String pool) { this.pool = pool; }
    public BigInteger getLpAmount() { return lpAmount; }
    public void setLpAmount(BigInteger lpAmount) { this.lpAmount = lpAmount; }
    public BigInteger getMinAmountA() { return minAmountA; }
    public void setMinAmountA(BigInteger minAmountA) { this.minAmountA = minAmountA; }
    public BigInteger getMinAmountB() { return minAmountB; }
    public void setMinAmountB(BigInteger minAmountB) { this.minAmountB = minAmountB; }
    public Long getDeadline() { return deadline; }
    public void setDeadline(Long deadline) { this.deadline = deadline; }
}

class LiquidityResult {
    public String transactionHash;
    public BigInteger amountA;
    public BigInteger amountB;
    public BigInteger lpTokens;
    public double poolShare;
}

class LPPosition {
    public String poolId;
    public BigInteger lpTokens;
    public BigInteger tokenAAmount;
    public BigInteger tokenBAmount;
    public double valueUsd;
    public BigInteger unclaimedFeesA;
    public BigInteger unclaimedFeesB;
    public double impermanentLoss;
    public Integer tickLower;
    public Integer tickUpper;
    public Boolean inRange;
}

class PerpMarket {
    public String symbol;
    public String baseAsset;
    public String quoteAsset;
    public double indexPrice;
    public double markPrice;
    public double fundingRate;
    public long nextFundingTime;
    public BigInteger openInterest;
    public double volume24h;
    public double priceChange24h;
    public int maxLeverage;
    public BigInteger minOrderSize;
    public double tickSize;
    public double maintenanceMargin;
    public double initialMargin;
}

class OpenPositionParams {
    private String market;
    private Types.PositionSide side;
    private BigInteger size;
    private int leverage;
    private Types.OrderType orderType;
    private Double limitPrice;
    private Double stopLoss;
    private Double takeProfit;
    private Types.MarginType marginType = Types.MarginType.CROSS;
    private boolean reduceOnly;

    public String getMarket() { return market; }
    public void setMarket(String market) { this.market = market; }
    public Types.PositionSide getSide() { return side; }
    public void setSide(Types.PositionSide side) { this.side = side; }
    public BigInteger getSize() { return size; }
    public void setSize(BigInteger size) { this.size = size; }
    public int getLeverage() { return leverage; }
    public void setLeverage(int leverage) { this.leverage = leverage; }
    public Types.OrderType getOrderType() { return orderType; }
    public void setOrderType(Types.OrderType orderType) { this.orderType = orderType; }
    public Double getLimitPrice() { return limitPrice; }
    public void setLimitPrice(Double limitPrice) { this.limitPrice = limitPrice; }
    public Double getStopLoss() { return stopLoss; }
    public void setStopLoss(Double stopLoss) { this.stopLoss = stopLoss; }
    public Double getTakeProfit() { return takeProfit; }
    public void setTakeProfit(Double takeProfit) { this.takeProfit = takeProfit; }
    public Types.MarginType getMarginType() { return marginType; }
    public void setMarginType(Types.MarginType marginType) { this.marginType = marginType; }
    public boolean isReduceOnly() { return reduceOnly; }
    public void setReduceOnly(boolean reduceOnly) { this.reduceOnly = reduceOnly; }
}

class ClosePositionParams {
    private String market;
    private BigInteger size;
    private Types.OrderType orderType = Types.OrderType.MARKET;
    private Double limitPrice;

    public String getMarket() { return market; }
    public void setMarket(String market) { this.market = market; }
    public BigInteger getSize() { return size; }
    public void setSize(BigInteger size) { this.size = size; }
    public Types.OrderType getOrderType() { return orderType; }
    public void setOrderType(Types.OrderType orderType) { this.orderType = orderType; }
    public Double getLimitPrice() { return limitPrice; }
    public void setLimitPrice(Double limitPrice) { this.limitPrice = limitPrice; }
}

class ModifyPositionParams {
    private String positionId;
    private Integer newLeverage;
    private BigInteger newMargin;
    private Double newStopLoss;
    private Double newTakeProfit;

    public String getPositionId() { return positionId; }
    public void setPositionId(String positionId) { this.positionId = positionId; }
    public Integer getNewLeverage() { return newLeverage; }
    public void setNewLeverage(Integer newLeverage) { this.newLeverage = newLeverage; }
    public BigInteger getNewMargin() { return newMargin; }
    public void setNewMargin(BigInteger newMargin) { this.newMargin = newMargin; }
    public Double getNewStopLoss() { return newStopLoss; }
    public void setNewStopLoss(Double newStopLoss) { this.newStopLoss = newStopLoss; }
    public Double getNewTakeProfit() { return newTakeProfit; }
    public void setNewTakeProfit(Double newTakeProfit) { this.newTakeProfit = newTakeProfit; }
}

class PerpPosition {
    public String id;
    public String market;
    public Types.PositionSide side;
    public BigInteger size;
    public double entryPrice;
    public double markPrice;
    public double liquidationPrice;
    public BigInteger margin;
    public int leverage;
    public BigInteger unrealizedPnl;
    public BigInteger realizedPnl;
    public double marginRatio;
    public Double stopLoss;
    public Double takeProfit;
    public long createdAt;
    public long updatedAt;
}

class PerpOrder {
    public String id;
    public String market;
    public Types.PositionSide side;
    public Types.OrderType orderType;
    public BigInteger size;
    public Double price;
    public BigInteger filledSize;
    public Types.OrderStatus status;
    public boolean reduceOnly;
    public long createdAt;
}

class FundingPayment {
    public String market;
    public BigInteger amount;
    public double rate;
    public BigInteger positionSize;
    public long timestamp;
}

class OrderBookEntry {
    public double price;
    public BigInteger size;
    public int orders;
}

class OrderBook {
    public String market;
    public List<OrderBookEntry> bids;
    public List<OrderBookEntry> asks;
    public long timestamp;
}

class LimitOrderParams {
    private String market;
    private String side;
    private double price;
    private BigInteger size;
    private Types.TimeInForce timeInForce = Types.TimeInForce.GTC;
    private boolean postOnly;

    public String getMarket() { return market; }
    public void setMarket(String market) { this.market = market; }
    public String getSide() { return side; }
    public void setSide(String side) { this.side = side; }
    public double getPrice() { return price; }
    public void setPrice(double price) { this.price = price; }
    public BigInteger getSize() { return size; }
    public void setSize(BigInteger size) { this.size = size; }
    public Types.TimeInForce getTimeInForce() { return timeInForce; }
    public void setTimeInForce(Types.TimeInForce timeInForce) { this.timeInForce = timeInForce; }
    public boolean isPostOnly() { return postOnly; }
    public void setPostOnly(boolean postOnly) { this.postOnly = postOnly; }
}

class Order {
    public String id;
    public String market;
    public String side;
    public double price;
    public BigInteger size;
    public BigInteger filledSize;
    public Types.OrderStatus status;
    public Types.TimeInForce timeInForce;
    public boolean postOnly;
    public long createdAt;
    public long updatedAt;
}

class Farm {
    public String id;
    public String name;
    public Token stakeToken;
    public List<Token> rewardTokens;
    public double tvlUsd;
    public double apr;
    public List<BigInteger> dailyRewards;
    public Long lockupPeriod;
    public BigInteger minStake;
}

class StakeParams {
    private String farm;
    private BigInteger amount;

    public String getFarm() { return farm; }
    public void setFarm(String farm) { this.farm = farm; }
    public BigInteger getAmount() { return amount; }
    public void setAmount(BigInteger amount) { this.amount = amount; }
}

class FarmPosition {
    public String farmId;
    public BigInteger stakedAmount;
    public List<BigInteger> pendingRewards;
    public long stakedAt;
    public Long unlockAt;
}

class OHLCV {
    public long timestamp;
    public double open;
    public double high;
    public double low;
    public double close;
    public double volume;
}

class TradeHistory {
    public String id;
    public String market;
    public String side;
    public double price;
    public BigInteger size;
    public long timestamp;
    public String maker;
    public String taker;
}

class VolumeStats {
    public double volume24h;
    public double volume7d;
    public double volume30d;
    public int trades24h;
    public int uniqueTraders24h;
}

class TVLStats {
    public double totalTvl;
    public double poolsTvl;
    public double farmsTvl;
    public double perpsTvl;
}

class ClaimRewardsResult {
    public BigInteger amount;
    public String transactionHash;
}

class FundingRateInfo {
    public double rate;
    public long nextTime;
}
