/*
 * This file is part of Stack Wallet.
 *
 * Copyright (c) 2023 Cypher Stack
 * All Rights Reserved.
 * The code is distributed under GPLv3 license, see LICENSE file for details.
 * Generated by Cypher Stack on 2023-05-26
 *
 */

import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
import 'package:stackwallet/utilities/constants.dart';

enum Coin {
  bitcoin,
  monero,
  banano,
  bitcoincash,
  bitcoinFrost,
  dogecoin,
  eCash,
  epicCash,
  ethereum,
  firo,
  litecoin,
  namecoin,
  nano,
  particl,
  solana,
  stellar,
  tezos,
  wownero,

  ///

  ///
  ///

  bitcoinTestNet,
  bitcoincashTestnet,
  bitcoinFrostTestNet,
  dogecoinTestNet,
  firoTestNet,
  litecoinTestNet,
  stellarTestnet,
}

extension CoinExt on Coin {
  String get prettyName {
    switch (this) {
      case Coin.bitcoin:
        return "Bitcoin";
      case Coin.bitcoinFrost:
        return "Bitcoin Frost";
      case Coin.litecoin:
        return "Litecoin";
      case Coin.bitcoincash:
        return "Bitcoin Cash";
      case Coin.dogecoin:
        return "Dogecoin";
      case Coin.epicCash:
        return "Epic Cash";
      case Coin.eCash:
        return "eCash";
      case Coin.ethereum:
        return "Ethereum";
      case Coin.firo:
        return "Firo";
      case Coin.monero:
        return "Monero";
      case Coin.particl:
        return "Particl";
      case Coin.solana:
        return "Solana";
      case Coin.stellar:
        return "Stellar";
      case Coin.tezos:
        return "Tezos";
      case Coin.wownero:
        return "Wownero";
      case Coin.namecoin:
        return "Namecoin";
      case Coin.nano:
        return "Nano";
      case Coin.banano:
        return "Banano";
      case Coin.bitcoinTestNet:
        return "tBitcoin";
      case Coin.bitcoinFrostTestNet:
        return "tBitcoin Frost";
      case Coin.litecoinTestNet:
        return "tLitecoin";
      case Coin.bitcoincashTestnet:
        return "tBitcoin Cash";
      case Coin.firoTestNet:
        return "tFiro";
      case Coin.dogecoinTestNet:
        return "tDogecoin";
      case Coin.stellarTestnet:
        return "tStellar";
    }
  }

  String get ticker {
    switch (this) {
      case Coin.bitcoin:
      case Coin.bitcoinFrost:
        return "BTC";
      case Coin.litecoin:
        return "LTC";
      case Coin.bitcoincash:
        return "BCH";
      case Coin.dogecoin:
        return "DOGE";
      case Coin.epicCash:
        return "EPIC";
      case Coin.ethereum:
        return "ETH";
      case Coin.eCash:
        return "XEC";
      case Coin.firo:
        return "FIRO";
      case Coin.monero:
        return "XMR";
      case Coin.particl:
        return "PART";
      case Coin.solana:
        return "SOL";
      case Coin.stellar:
        return "XLM";
      case Coin.tezos:
        return "XTZ";
      case Coin.wownero:
        return "WOW";
      case Coin.namecoin:
        return "NMC";
      case Coin.nano:
        return "XNO";
      case Coin.banano:
        return "BAN";
      case Coin.bitcoinTestNet:
      case Coin.bitcoinFrostTestNet:
        return "tBTC";
      case Coin.litecoinTestNet:
        return "tLTC";
      case Coin.bitcoincashTestnet:
        return "tBCH";
      case Coin.firoTestNet:
        return "tFIRO";
      case Coin.dogecoinTestNet:
        return "tDOGE";
      case Coin.stellarTestnet:
        return "tXLM";
    }
  }

  String get uriScheme {
    switch (this) {
      case Coin.bitcoin:
      case Coin.bitcoinFrost:
        return "bitcoin";
      case Coin.litecoin:
        return "litecoin";
      case Coin.bitcoincash:
        return "bitcoincash";
      case Coin.dogecoin:
        return "dogecoin";
      case Coin.epicCash:
        // TODO: is this actually the right one?
        return "epic";
      case Coin.ethereum:
        return "ethereum";
      case Coin.eCash:
        return "ecash";
      case Coin.firo:
        return "firo";
      case Coin.monero:
        return "monero";
      case Coin.particl:
        return "particl";
      case Coin.solana:
        return "solana";
      case Coin.stellar:
        return "stellar";
      case Coin.tezos:
        return "tezos";
      case Coin.wownero:
        return "wownero";
      case Coin.namecoin:
        return "namecoin";
      case Coin.nano:
        return "nano";
      case Coin.banano:
        return "ban";
      case Coin.bitcoinTestNet:
      case Coin.bitcoinFrostTestNet:
        return "bitcoin";
      case Coin.litecoinTestNet:
        return "litecoin";
      case Coin.bitcoincashTestnet:
        return "bchtest";
      case Coin.firoTestNet:
        return "firo";
      case Coin.dogecoinTestNet:
        return "dogecoin";
      case Coin.stellarTestnet:
        return "stellar";
    }
  }

  bool get hasMnemonicPassphraseSupport {
    switch (this) {
      case Coin.bitcoin:
      case Coin.bitcoinTestNet:
      case Coin.litecoin:
      case Coin.litecoinTestNet:
      case Coin.bitcoincash:
      case Coin.bitcoincashTestnet:
      case Coin.dogecoin:
      case Coin.dogecoinTestNet:
      case Coin.firo:
      case Coin.firoTestNet:
      case Coin.namecoin:
      case Coin.particl:
      case Coin.ethereum:
      case Coin.eCash:
      case Coin.stellar:
      case Coin.stellarTestnet:
        return true;

      case Coin.bitcoinFrost:
      case Coin.bitcoinFrostTestNet:
      case Coin.epicCash:
      case Coin.monero:
      case Coin.wownero:
      case Coin.nano:
      case Coin.banano:
      case Coin.tezos:
      case Coin.solana:
        return false;
    }
  }

  bool get hasBuySupport {
    switch (this) {
      case Coin.bitcoin:
      case Coin.litecoin:
      case Coin.bitcoincash:
      case Coin.dogecoin:
      case Coin.ethereum:
        return true;

      case Coin.bitcoinFrost:
      case Coin.bitcoinFrostTestNet:
      case Coin.firo:
      case Coin.namecoin:
      case Coin.particl:
      case Coin.eCash:
      case Coin.epicCash:
      case Coin.monero:
      case Coin.tezos:
      case Coin.wownero:
      case Coin.dogecoinTestNet:
      case Coin.bitcoinTestNet:
      case Coin.litecoinTestNet:
      case Coin.bitcoincashTestnet:
      case Coin.firoTestNet:
      case Coin.nano:
      case Coin.banano:
      case Coin.solana:
      case Coin.stellar:
      case Coin.stellarTestnet:
        return false;
    }
  }

  bool get isTestNet {
    switch (this) {
      case Coin.bitcoin:
      case Coin.bitcoinFrost:
      case Coin.litecoin:
      case Coin.bitcoincash:
      case Coin.dogecoin:
      case Coin.firo:
      case Coin.namecoin:
      case Coin.particl:
      case Coin.epicCash:
      case Coin.ethereum:
      case Coin.monero:
      case Coin.tezos:
      case Coin.wownero:
      case Coin.nano:
      case Coin.banano:
      case Coin.eCash:
      case Coin.stellar:
      case Coin.solana:
        return false;

      case Coin.dogecoinTestNet:
      case Coin.bitcoinTestNet:
      case Coin.bitcoinFrostTestNet:
      case Coin.litecoinTestNet:
      case Coin.bitcoincashTestnet:
      case Coin.firoTestNet:
      case Coin.stellarTestnet:
        return true;
    }
  }

  bool get isFrost {
    switch (this) {
      case Coin.bitcoinFrost:
      case Coin.bitcoinFrostTestNet:
        return true;

      default:
        return false;
    }
  }

  Coin get mainNetVersion {
    switch (this) {
      case Coin.bitcoin:
      case Coin.bitcoinFrost:
      case Coin.litecoin:
      case Coin.bitcoincash:
      case Coin.dogecoin:
      case Coin.firo:
      case Coin.namecoin:
      case Coin.particl:
      case Coin.epicCash:
      case Coin.ethereum:
      case Coin.monero:
      case Coin.tezos:
      case Coin.wownero:
      case Coin.nano:
      case Coin.banano:
      case Coin.eCash:
      case Coin.stellar:
      case Coin.solana:
        return this;

      case Coin.dogecoinTestNet:
        return Coin.dogecoin;

      case Coin.bitcoinTestNet:
        return Coin.bitcoin;

      case Coin.bitcoinFrostTestNet:
        return Coin.bitcoinFrost;

      case Coin.litecoinTestNet:
        return Coin.litecoin;

      case Coin.bitcoincashTestnet:
        return Coin.bitcoincash;

      case Coin.firoTestNet:
        return Coin.firo;

      case Coin.stellarTestnet:
        return Coin.stellar;
    }
  }

  int get decimals => Constants.decimalPlacesForCoin(this);

  // Note: this must relate to DerivePathType for certain coins!
  AddressType get primaryAddressType {
    switch (this) {
      case Coin.bitcoin:
      case Coin.bitcoinTestNet:
      case Coin.litecoin:
      case Coin.litecoinTestNet:
      case Coin.namecoin:
      case Coin.particl:
        return AddressType.p2wpkh;

      case Coin.bitcoinFrost:
      case Coin.bitcoinFrostTestNet:
        return AddressType.frostMS;

      case Coin.eCash:
      case Coin.bitcoincash:
      case Coin.bitcoincashTestnet:
      case Coin.dogecoin:
      case Coin.firo:
      case Coin.firoTestNet:
      case Coin.dogecoinTestNet:
        return AddressType.p2pkh;

      case Coin.monero:
      case Coin.wownero:
        return AddressType.cryptonote;

      case Coin.epicCash:
        return AddressType.mimbleWimble;

      case Coin.ethereum:
        return AddressType.ethereum;

      case Coin.tezos:
        return AddressType.tezos;

      case Coin.nano:
        return AddressType.nano;

      case Coin.banano:
        return AddressType.banano;

      case Coin.stellar:
      case Coin.stellarTestnet:
        return AddressType.stellar;

      case Coin.solana:
        return AddressType.solana;
    }
  }
}

Coin coinFromPrettyName(String name) {
  switch (name) {
    case "Bitcoin":
    case "bitcoin":
      return Coin.bitcoin;

    case "Litecoin":
    case "litecoin":
      return Coin.litecoin;

    case "Bitcoincash":
    case "bitcoincash":
    case "Bitcoin Cash":
      return Coin.bitcoincash;

    case "Dogecoin":
    case "dogecoin":
      return Coin.dogecoin;

    case "Epic Cash":
    case "epicCash":
      return Coin.epicCash;

    case "Ethereum":
    case "ethereum":
      return Coin.ethereum;

    case "Firo":
    case "firo":
      return Coin.firo;

    case "E-Cash":
    case "ecash":
    case "eCash":
      return Coin.eCash;

    case "Monero":
    case "monero":
      return Coin.monero;

    case "Particl":
    case "particl":
      return Coin.particl;

    case "Solana":
    case "solana":
      return Coin.solana;

    case "Stellar":
    case "stellar":
      return Coin.stellar;

    case "Tezos":
    case "tezos":
      return Coin.tezos;

    case "Namecoin":
    case "namecoin":
      return Coin.namecoin;

    case "Bitcoin Testnet":
    case "tBitcoin":
    case "bitcoinTestNet":
      return Coin.bitcoinTestNet;

    case "Litecoin Testnet":
    case "tlitecoin":
    case "litecoinTestNet":
    case "tLitecoin":
      return Coin.litecoinTestNet;

    case "Bitcoincash Testnet":
    case "tBitcoin Cash":
    case "Bitcoin Cash Testnet":
    case "bitcoincashTestnet":
      return Coin.bitcoincashTestnet;

    case "Firo Testnet":
    case "tFiro":
    case "firoTestNet":
      return Coin.firoTestNet;

    case "Dogecoin Testnet":
    case "tDogecoin":
    case "dogecoinTestNet":
      return Coin.dogecoinTestNet;

    case "Wownero":
    case "tWownero":
    case "wownero":
      return Coin.wownero;

    case "Nano":
    case "nano":
      return Coin.nano;

    case "Banano":
    case "banano":
      return Coin.banano;

    case "Stellar Testnet":
    case "stellarTestnet":
    case "stellarTestNet":
    case "tStellar":
      return Coin.stellarTestnet;

    case "Bitcoin Frost":
    case "bitcoinFrost":
      return Coin.bitcoinFrost;

    case "Bitcoin Frost Testnet":
    case "tBitcoin Frost":
    case "bitcoinFrostTestNet":
      return Coin.bitcoinFrostTestNet;

    default:
      throw ArgumentError.value(
        name,
        "name",
        "No Coin enum value with that prettyName",
      );
  }
}

Coin coinFromTickerCaseInsensitive(String ticker) {
  switch (ticker.toLowerCase()) {
    case "btc":
      return Coin.bitcoin;
    case "ltc":
      return Coin.litecoin;
    case "bch":
      return Coin.bitcoincash;
    case "doge":
      return Coin.dogecoin;
    case "epic":
      return Coin.epicCash;
    case "xec":
      return Coin.eCash;
    case "eth":
      return Coin.ethereum;
    case "firo":
      return Coin.firo;
    case "xmr":
      return Coin.monero;
    case "nmc":
      return Coin.namecoin;
    case "part":
      return Coin.particl;
    case "sol":
      return Coin.solana;
    case "xlm":
      return Coin.stellar;
    case "xtz":
      return Coin.tezos;
    case "tltc":
      return Coin.litecoinTestNet;
    case "tbtc":
      return Coin.bitcoinTestNet;
    case "tbch":
      return Coin.bitcoincashTestnet;
    case "tfiro":
      return Coin.firoTestNet;
    case "tdoge":
      return Coin.dogecoinTestNet;
    case "wow":
      return Coin.wownero;
    case "xno":
      return Coin.nano;
    case "ban":
      return Coin.banano;
    case "txlm":
      return Coin.stellarTestnet;
    default:
      throw ArgumentError.value(
          ticker, "name", "No Coin enum value with that ticker");
  }
}