import { Repositories } from './repositories.factory';
import { Services } from './services.factory';
import { CreateDeviceUseCase } from '../../application/use-cases/device/create-device.use-case';
import { GetDeviceByIdUseCase } from '../../application/use-cases/device/get-device-by-id.use-case';
import { GetAllDevicesUseCase } from '../../application/use-cases/device/get-all-devices.use-case';
import { UpdateDeviceStatusUseCase } from '../../application/use-cases/device/update-device-status.use-case';
import { UpdateDevicePushTokenUseCase } from '../../application/use-cases/device/update-device-push-token.use-case';
import { GenerateWalletSeedphraseUseCase } from '../../application/use-cases/wallet/generate-seedphrase.use-case';
import { CreateWalletUseCase } from '../../application/use-cases/wallet/create-wallet.use-case';
import { GetWalletByIdUseCase } from '../../application/use-cases/wallet/get-wallet-by-id.use-case';
import { GetWalletsByDeviceUseCase } from '../../application/use-cases/wallet/get-wallets-by-device.use-case';
import { GetWalletAddressForNetworkUseCase } from '../../application/use-cases/wallet/get-wallet-address-for-network.use-case';
import { GetAllNetworkAddressesForWalletUseCase } from '../../application/use-cases/wallet/get-all-network-addresses-for-wallet.use-case';
import { GetWalletSeedPhraseUseCase } from '../../application/use-cases/wallet/get-wallet-seed-phrase.use-case';
import { GetAddressByAddressUseCase } from '../../application/use-cases/address/get-address-by-address.use-case';
import { GetNetworksListUseCase } from '../../application/use-cases/network/get-networks-list.use-case';
import { GetNetworkGasInfoUseCase } from '../../application/use-cases/network/get-network-gas-info.use-case';
import { GetTokenByIdUseCase } from '../../application/use-cases/token/get-token-by-id.use-case';
import { GetTokensByNetworkUseCase } from '../../application/use-cases/token/get-tokens-by-network.use-case';
import { GetAllTokensUseCase } from '../../application/use-cases/token/get-all-tokens.use-case';
import { GetTokenChartUseCase } from '../../application/use-cases/token/get-token-chart.use-case';
import { GetTokenPricesUseCase } from '../../application/use-cases/token/get-token-prices.use-case';
import { GetTokenBySymbolUseCase } from '../../application/use-cases/token/get-token-by-symbol.use-case';
import { ResolveTokenByContractUseCase } from '../../application/use-cases/token/resolve-token-by-contract.use-case';
import { GetWalletBalancesForNetworkUseCase } from '../../application/use-cases/balance/get-wallet-balances-for-network.use-case';
import { GetAllWalletBalancesUseCase } from '../../application/use-cases/balance/get-all-wallet-balances.use-case';
import { CreateTransactionUseCase } from '../../application/use-cases/transaction/create-transaction.use-case';
import { GetTransactionsUseCase } from '../../application/use-cases/transaction/get-transactions.use-case';
import { GetTransactionByIdUseCase } from '../../application/use-cases/transaction/get-transaction-by-id.use-case';
import { UpdateTransactionUseCase } from '../../application/use-cases/transaction/update-transaction.use-case';
import { TransactionRateUseCase } from '../../application/use-cases/transaction/transaction-rate.use-case';
import { CreateNetworkUseCase } from '../../application/use-cases/admin/create-network.use-case';
import { CreateTokenUseCase } from '../../application/use-cases/admin/create-token.use-case';
import { UpdateTokenUseCase } from '../../application/use-cases/admin/update-token.use-case';
import { DeleteTokenUseCase } from '../../application/use-cases/admin/delete-token.use-case';
import { UpdateTokenMinimumSwapValueUseCase } from '../../application/use-cases/admin/update-token-minimum-swap-value.use-case';
import { FetchTokenDataUseCase } from '../../application/use-cases/admin/fetch-token-data.use-case';
import { GetImageUseCase } from '../../application/use-cases/image/get-image.use-case';

export interface UseCases {
  createDevice: CreateDeviceUseCase;
  getDeviceById: GetDeviceByIdUseCase;
  getAllDevices: GetAllDevicesUseCase;
  updateDeviceStatus: UpdateDeviceStatusUseCase;
  updateDevicePushToken: UpdateDevicePushTokenUseCase;
  generateWalletSeedphrase: GenerateWalletSeedphraseUseCase;
  createWallet: CreateWalletUseCase;
  getWalletById: GetWalletByIdUseCase;
  getWalletsByDevice: GetWalletsByDeviceUseCase;
  getWalletAddressForNetwork: GetWalletAddressForNetworkUseCase;
  getAllNetworkAddressesForWallet: GetAllNetworkAddressesForWalletUseCase;
  getWalletSeedPhrase: GetWalletSeedPhraseUseCase;
  getAddressByAddress: GetAddressByAddressUseCase;
  getNetworksList: GetNetworksListUseCase;
  getNetworkGasInfo: GetNetworkGasInfoUseCase;
  getTokenById: GetTokenByIdUseCase;
  getTokenBySymbol: GetTokenBySymbolUseCase;
  getTokensByNetwork: GetTokensByNetworkUseCase;
  getAllTokens: GetAllTokensUseCase;
  getTokenChart: GetTokenChartUseCase;
  getTokenPrices: GetTokenPricesUseCase;
  resolveTokenByContract: ResolveTokenByContractUseCase;
  getWalletBalancesForNetwork: GetWalletBalancesForNetworkUseCase;
  getAllWalletBalances: GetAllWalletBalancesUseCase;
  createTransaction: CreateTransactionUseCase;
  getTransactions: GetTransactionsUseCase;
  getTransactionById: GetTransactionByIdUseCase;
  updateTransaction: UpdateTransactionUseCase;
  transactionRate: TransactionRateUseCase;
  createNetwork: CreateNetworkUseCase;
  createToken: CreateTokenUseCase;
  updateToken: UpdateTokenUseCase;
  deleteToken: DeleteTokenUseCase;
  updateTokenMinimumSwapValue: UpdateTokenMinimumSwapValueUseCase;
  fetchTokenData: FetchTokenDataUseCase;
  getImage: GetImageUseCase;
}

export const createUseCases = (repositories: Repositories, services: Services): UseCases => {
  const createNetworkUseCase = new CreateNetworkUseCase(
    repositories.networkRepository,
    services.imageStorage,
  );
  const createTokenUseCase = new CreateTokenUseCase(
    repositories.tokenRepository,
    repositories.networkRepository,
    services.imageStorage,
    services.coinMarketCapClient,
    services.logger,
  );

  return {
    createDevice: new CreateDeviceUseCase(repositories.deviceRepository),
    getDeviceById: new GetDeviceByIdUseCase(repositories.deviceRepository),
    getAllDevices: new GetAllDevicesUseCase(repositories.deviceRepository),
    updateDeviceStatus: new UpdateDeviceStatusUseCase(repositories.deviceRepository),
    updateDevicePushToken: new UpdateDevicePushTokenUseCase(repositories.deviceRepository),

    generateWalletSeedphrase: new GenerateWalletSeedphraseUseCase(services.seedPhraseService),
    createWallet: new CreateWalletUseCase(
      repositories.walletRepository,
      repositories.deviceRepository,
      repositories.addressRepository,
      repositories.networkRepository,
      services.encryptionService,
      services.addressGenerator,
    ),
    getWalletById: new GetWalletByIdUseCase(repositories.walletRepository),
    getWalletsByDevice: new GetWalletsByDeviceUseCase(repositories.walletRepository),
    getWalletAddressForNetwork: new GetWalletAddressForNetworkUseCase(
      repositories.walletRepository,
      repositories.networkRepository,
      repositories.addressRepository,
      services.addressGenerator,
    ),
    getAllNetworkAddressesForWallet: new GetAllNetworkAddressesForWalletUseCase(
      repositories.walletRepository,
      repositories.addressRepository,
    ),
    getWalletSeedPhrase: new GetWalletSeedPhraseUseCase(
      repositories.walletRepository,
      services.encryptionService,
    ),
    getAddressByAddress: new GetAddressByAddressUseCase(repositories.addressRepository),

    getNetworksList: new GetNetworksListUseCase(
      repositories.networkRepository,
      services.cacheService,
    ),
    getNetworkGasInfo: new GetNetworkGasInfoUseCase(
      repositories.networkRepository,
      services.networkRpcClient,
    ),

    getTokenById: new GetTokenByIdUseCase(repositories.tokenRepository),
    getTokenBySymbol: new GetTokenBySymbolUseCase(repositories.tokenRepository),
    getTokensByNetwork: new GetTokensByNetworkUseCase(
      repositories.tokenRepository,
      repositories.networkRepository,
      services.cacheService,
    ),
    getAllTokens: new GetAllTokensUseCase(repositories.tokenRepository, services.cacheService),
    getTokenChart: new GetTokenChartUseCase(
      repositories.tokenRepository,
      services.coinMarketCapClient,
    ),
    getTokenPrices: new GetTokenPricesUseCase(services.coinMarketCapClient),
    resolveTokenByContract: new ResolveTokenByContractUseCase(
      repositories.networkRepository,
      repositories.tokenRepository,
      createTokenUseCase,
      services.coinMarketCapClient,
      services.networkRpcClient,
      services.logger,
    ),

    getWalletBalancesForNetwork: new GetWalletBalancesForNetworkUseCase(
      repositories.walletRepository,
      repositories.networkRepository,
      repositories.addressRepository,
      repositories.tokenRepository,
      repositories.transactionRepository,
      services.balanceService,
    ),
    getAllWalletBalances: new GetAllWalletBalancesUseCase(
      repositories.walletRepository,
      repositories.addressRepository,
      repositories.tokenRepository,
      repositories.transactionRepository,
      services.balanceService,
    ),

    createTransaction: new CreateTransactionUseCase(
      repositories.transactionRepository,
      repositories.networkRepository,
      repositories.addressRepository,
      repositories.tokenRepository,
      services.eventPublisher,
    ),
    getTransactions: new GetTransactionsUseCase(
      repositories.transactionRepository,
      repositories.addressRepository,
    ),
    getTransactionById: new GetTransactionByIdUseCase(
      repositories.transactionRepository,
      repositories.addressRepository,
    ),
    updateTransaction: new UpdateTransactionUseCase(
      repositories.transactionRepository,
      services.eventPublisher,
    ),
    transactionRate: new TransactionRateUseCase(
      repositories.networkRepository,
      repositories.tokenRepository,
      services.coinMarketCapClient,
    ),

    createNetwork: createNetworkUseCase,
    createToken: createTokenUseCase,
    updateToken: new UpdateTokenUseCase(
      repositories.tokenRepository,
      repositories.networkRepository,
      services.imageStorage,
      services.coinMarketCapClient,
      services.logger,
    ),
    deleteToken: new DeleteTokenUseCase(repositories.tokenRepository),
    updateTokenMinimumSwapValue: new UpdateTokenMinimumSwapValueUseCase(repositories.tokenRepository),
    fetchTokenData: new FetchTokenDataUseCase(
      repositories.networkRepository,
      repositories.tokenRepository,
      services.coinMarketCapClient,
      services.logger,
    ),
    getImage: new GetImageUseCase(services.imageStorage),
  };
};
