/*
 * This file is part of Bisq.
 *
 * Bisq is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 *
 * Bisq is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Bisq. If not, see <http://www.gnu.org/licenses/>.
 */

package bisq.core.api;

import bisq.core.api.model.AddressBalanceInfo;
import bisq.core.monetary.Price;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferPayload;
import bisq.core.payment.PaymentAccount;
import bisq.core.trade.handlers.TransactionResultHandler;
import bisq.core.trade.statistics.TradeStatistics2;
import bisq.core.trade.statistics.TradeStatisticsManager;

import bisq.common.app.Version;

import org.bitcoinj.core.Coin;

import javax.inject.Inject;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import lombok.extern.slf4j.Slf4j;

/**
 * Provides high level interface to functionality of core Bisq features.
 * E.g. useful for different APIs to access data of different domains of Bisq.
 */
@Slf4j
public class CoreApi {

    private final CoreOffersService coreOffersService;
    private final CorePaymentAccountsService paymentAccountsService;
    private final CoreWalletsService walletsService;
    private final TradeStatisticsManager tradeStatisticsManager;

    @Inject
    public CoreApi(CoreOffersService coreOffersService,
                   CorePaymentAccountsService paymentAccountsService,
                   CoreWalletsService walletsService,
                   TradeStatisticsManager tradeStatisticsManager) {
        this.coreOffersService = coreOffersService;
        this.paymentAccountsService = paymentAccountsService;
        this.walletsService = walletsService;
        this.tradeStatisticsManager = tradeStatisticsManager;
    }

    public String getVersion() {
        return Version.VERSION;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // Offers
    ///////////////////////////////////////////////////////////////////////////////////////////

    public List<Offer> getOffers(String direction, String fiatCurrencyCode) {
        return coreOffersService.getOffers(direction, fiatCurrencyCode);
    }

    public void createOffer(String currencyCode,
                            String directionAsString,
                            long priceAsLong,
                            boolean useMarketBasedPrice,
                            double marketPriceMargin,
                            long amountAsLong,
                            long minAmountAsLong,
                            double buyerSecurityDeposit,
                            String paymentAccountId,
                            TransactionResultHandler resultHandler) {
        coreOffersService.createOffer(currencyCode,
                directionAsString,
                priceAsLong,
                useMarketBasedPrice,
                marketPriceMargin,
                amountAsLong,
                minAmountAsLong,
                buyerSecurityDeposit,
                paymentAccountId,
                resultHandler);
    }

    public void createOffer(String offerId,
                            String currencyCode,
                            OfferPayload.Direction direction,
                            Price price,
                            boolean useMarketBasedPrice,
                            double marketPriceMargin,
                            Coin amount,
                            Coin minAmount,
                            double buyerSecurityDeposit,
                            PaymentAccount paymentAccount,
                            boolean useSavingsWallet,
                            TransactionResultHandler resultHandler) {
        coreOffersService.createOffer(offerId,
                currencyCode,
                direction,
                price,
                useMarketBasedPrice,
                marketPriceMargin,
                amount,
                minAmount,
                buyerSecurityDeposit,
                paymentAccount,
                useSavingsWallet,
                resultHandler);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // PaymentAccounts
    ///////////////////////////////////////////////////////////////////////////////////////////

    public void createPaymentAccount(String accountName, String accountNumber, String fiatCurrencyCode) {
        paymentAccountsService.createPaymentAccount(accountName, accountNumber, fiatCurrencyCode);
    }

    public Set<PaymentAccount> getPaymentAccounts() {
        return paymentAccountsService.getPaymentAccounts();
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // Wallets
    ///////////////////////////////////////////////////////////////////////////////////////////

    public long getAvailableBalance() {
        return walletsService.getAvailableBalance();
    }

    public long getAddressBalance(String addressString) {
        return walletsService.getAddressBalance(addressString);
    }

    public AddressBalanceInfo getAddressBalanceInfo(String addressString) {
        return walletsService.getAddressBalanceInfo(addressString);
    }

    public List<AddressBalanceInfo> getFundingAddresses() {
        return walletsService.getFundingAddresses();
    }

    public void setWalletPassword(String password, String newPassword) {
        walletsService.setWalletPassword(password, newPassword);
    }

    public void lockWallet() {
        walletsService.lockWallet();
    }

    public void unlockWallet(String password, long timeout) {
        walletsService.unlockWallet(password, timeout);
    }

    public void removeWalletPassword(String password) {
        walletsService.removeWalletPassword(password);
    }

    public List<TradeStatistics2> getTradeStatistics() {
        return new ArrayList<>(tradeStatisticsManager.getObservableTradeStatisticsSet());
    }

    public int getNumConfirmationsForMostRecentTransaction(String addressString) {
        return walletsService.getNumConfirmationsForMostRecentTransaction(addressString);
    }
}

@@ -1148,16 +1148,47 @@
 .Inject;
+%0Aimport javax.inject.Singleton;
 %0A%0Aimport
@@ -1450,16 +1450,27 @@
 sq.%0A */%0A
+@Singleton%0A
 @Slf4j%0Ap

Make CoreApi a singleton