import os
from configparser import ConfigParser

MAX_CLIENT_ID_LENGTH = 128
MAX_DATA_SIZE = 256
MAX_MEMO_CHARACTERS = 256

devnet_config = ConfigParser()
devnet_config.read(os.path.join(os.path.dirname(__file__), "denoms_devnet.ini"))

testnet_config = ConfigParser()
testnet_config.read(os.path.join(os.path.dirname(__file__), "denoms_testnet.ini"))

mainnet_config = ConfigParser()
mainnet_config.read(os.path.join(os.path.dirname(__file__), "denoms_mainnet.ini"))

class Denom:
    def __init__(
        self,
        description: str,
        base: int,
        quote: int,
        min_price_tick_size: float,
        min_quantity_tick_size: float
    ):
        self.description = description
        self.base = base
        self.quote = quote
        self.min_price_tick_size = min_price_tick_size
        self.min_quantity_tick_size = min_quantity_tick_size

    @classmethod
    def load_market(cls, network, market_id):
        if network == "devnet":
            config = devnet_config
        elif network == "testnet":
            config = testnet_config
        else:
            config =mainnet_config

        return cls(
            description=config[market_id]["description"],
            base=int(config[market_id]["base"]),
            quote=int(config[market_id]["quote"]),
            min_price_tick_size=float(config[market_id]["min_price_tick_size"]),
            min_quantity_tick_size=float(config[market_id]["min_quantity_tick_size"]),
        )

    @classmethod
    def load_peggy_denom(cls, network, symbol):
        if network == "devnet":
            config = devnet_config
        elif network == "local":
            config = devnet_config
        elif network == "testnet":
            config = testnet_config
        else:
            config = mainnet_config
        return config[symbol]["peggy_denom"], int(config[symbol]["decimals"])


class Network:
    def __init__(
        self,
        lcd_endpoint: str ,
        tm_websocket_endpoint: str,
        grpc_endpoint: str ,
        grpc_exchange_endpoint: str ,
        grpc_explorer_endpoint: str ,
        chain_id: str ,
        fee_denom: str ,
        env: str
    ):
        self.lcd_endpoint = lcd_endpoint
        self.tm_websocket_endpoint = tm_websocket_endpoint
        self.grpc_endpoint = grpc_endpoint
        self.grpc_exchange_endpoint = grpc_exchange_endpoint
        self.grpc_explorer_endpoint = grpc_explorer_endpoint
        self.chain_id = chain_id
        self.fee_denom = fee_denom
        self.env = env

    @classmethod
    def devnet(cls):
        return cls(
            lcd_endpoint="https://devnet.lcd.injective.dev",
            tm_websocket_endpoint="wss://devnet.tm.injective.dev/websocket",
            grpc_endpoint="devnet.injective.dev:9900",
            grpc_exchange_endpoint="devnet.injective.dev:9910",
            grpc_explorer_endpoint="devnet.injective.dev:9911",
            chain_id="injective-777",
            fee_denom="inj",
            env="devnet"
        )

    @classmethod
    def testnet(cls, node="lb"):
        nodes = [
            "lb",
            "sentry",
        ]
        if node not in nodes:
            raise ValueError("Must be one of {}".format(nodes))

        if node == "lb":
            lcd_endpoint = "https://k8s.testnet.lcd.injective.network"
            tm_websocket_endpoint = "wss://k8s.testnet.tm.injective.network/websocket"
            grpc_endpoint = "k8s.testnet.chain.grpc.injective.network:443"
            grpc_exchange_endpoint = "k8s.testnet.exchange.grpc.injective.network:443"
            grpc_explorer_endpoint = "k8s.testnet.explorer.grpc.injective.network:443"
        else:
            lcd_endpoint = "https://testnet.lcd.injective.network"
            tm_websocket_endpoint = "wss://testnet.tm.injective.network/websocket"
            grpc_endpoint = "testnet.chain.grpc.injective.network"
            grpc_exchange_endpoint = "testnet.exchange.grpc.injective.network"
            grpc_explorer_endpoint = "testnet.explorer.grpc.injective.network"

        return cls(
            lcd_endpoint=lcd_endpoint,
            tm_websocket_endpoint=tm_websocket_endpoint,
            grpc_endpoint=grpc_endpoint,
            grpc_exchange_endpoint=grpc_exchange_endpoint,
            grpc_explorer_endpoint=grpc_explorer_endpoint,
            chain_id="injective-888",
            fee_denom="inj",
            env="testnet"
        )

    @classmethod
    def mainnet(cls, node="lb"):
        nodes = [
            "lb", # us, asia, prod
            "sentry0",  # ca, prod
            "sentry1",  # ca, prod
            "sentry3",  # us, prod
        ]
        if node not in nodes:
            raise ValueError("Must be one of {}".format(nodes))

        if node == "lb":
            lcd_endpoint = "https://k8s.global.mainnet.lcd.injective.network:443"
            tm_websocket_endpoint = "wss://k8s.global.mainnet.tm.injective.network:443/websocket"
            grpc_endpoint = "k8s.global.mainnet.chain.grpc.injective.network:443"
            grpc_exchange_endpoint = "k8s.global.mainnet.exchange.grpc.injective.network:443"
            grpc_explorer_endpoint = "k8s.global.mainnet.explorer.grpc.injective.network:443"
        else:
            lcd_endpoint = f"http://{node}.injective.network:10337"
            tm_websocket_endpoint = f"ws://{node}.injective.network:26657/websocket"
            grpc_endpoint = f"{node}.injective.network:9900"
            grpc_exchange_endpoint = f"{node}.injective.network:9910"
            grpc_explorer_endpoint = f"{node}.injective.network:9911"

        return cls(
            lcd_endpoint=lcd_endpoint,
            tm_websocket_endpoint=tm_websocket_endpoint,
            grpc_endpoint=grpc_endpoint,
            grpc_exchange_endpoint=grpc_exchange_endpoint,
            grpc_explorer_endpoint=grpc_explorer_endpoint,
            chain_id="injective-1",
            fee_denom="inj",
            env="mainnet"
        )

    @classmethod
    def local(cls):
        return cls(
            lcd_endpoint="http://localhost:10337",
            tm_websocket_endpoint="ws://localhost:26657/websocket",
            grpc_endpoint="localhost:9900",
            grpc_exchange_endpoint="localhost:9910",
            grpc_explorer_endpoint="localhost:9911",
            chain_id="injective-1",
            fee_denom="inj",
            env="local"
        )

    @classmethod
    def custom(cls, lcd_endpoint, tm_websocket_endpoint, grpc_endpoint, grpc_exchange_endpoint, grpc_explorer_endpoint, chain_id, env):
        return cls(
            lcd_endpoint=lcd_endpoint,
            tm_websocket_endpoint=tm_websocket_endpoint,
            grpc_endpoint=grpc_endpoint,
            grpc_exchange_endpoint=grpc_exchange_endpoint,
            grpc_explorer_endpoint=grpc_explorer_endpoint,
            chain_id=chain_id,
            fee_denom="inj",
            env=env
        )

    def string(self):
        return self.env
