<commit_before>package io.bisq.core.user;

import com.google.common.collect.Maps;
import com.google.protobuf.Message;
import io.bisq.common.locale.Country;
import io.bisq.common.locale.CryptoCurrency;
import io.bisq.common.locale.FiatCurrency;
import io.bisq.common.locale.TradeCurrency;
import io.bisq.common.proto.ProtoUtil;
import io.bisq.common.proto.persistable.PersistableEnvelope;
import io.bisq.core.btc.Restrictions;
import io.bisq.core.payment.PaymentAccount;
import io.bisq.core.proto.CoreProtoResolver;
import io.bisq.generated.protobuffer.PB;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Data
@AllArgsConstructor
public final class PreferencesPayload implements PersistableEnvelope {
    private String userLanguage;
    private Country userCountry;
    @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
    private List<FiatCurrency> fiatCurrencies = new ArrayList<>();
    @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
    private List<CryptoCurrency> cryptoCurrencies = new ArrayList<>();
    private BlockChainExplorer blockChainExplorerMainNet;
    private BlockChainExplorer blockChainExplorerTestNet;
    private BlockChainExplorer bsqBlockChainExplorer = Preferences.BSQ_MAIN_NET_EXPLORER;
    @Nullable
    private String backupDirectory;
    private boolean autoSelectArbitrators = true;
    private Map<String, Boolean> dontShowAgainMap = new HashMap<>();
    private boolean tacAccepted;
    private boolean useTorForBitcoinJ = true;
    private boolean showOwnOffersInOfferBook = true;
    @Nullable
    private TradeCurrency preferredTradeCurrency;
    private long withdrawalTxFeeInBytes = 100;
    private boolean useCustomWithdrawalTxFee = false;
    private double maxPriceDistanceInPercent = 0.1;
    @Nullable
    private String offerBookChartScreenCurrencyCode;
    @Nullable
    private String tradeChartsScreenCurrencyCode;
    @Nullable
    private String buyScreenCurrencyCode;
    @Nullable
    private String sellScreenCurrencyCode;
    private int tradeStatisticsTickUnitIndex = 3;
    private boolean resyncSpvRequested;
    private boolean sortMarketCurrenciesNumerically = true;
    private boolean usePercentageBasedPrice = true;
    private Map<String, String> peerTagMap = new HashMap<>();
    private String bitcoinNodes = "";
    private List<String> ignoreTradersList = new ArrayList<>();
    private String directoryChooserPath;
    private long buyerSecurityDepositAsLong = Restrictions.getDefaultBuyerSecurityDeposit().value;
    private boolean useAnimations;
    @Nullable
    private PaymentAccount selectedPaymentAccountForCreateOffer;
    private boolean payFeeInBtc = true;
    @Nullable
    private List<String> bridgeAddresses = new ArrayList<>();


    ///////////////////////////////////////////////////////////////////////////////////////////
    // Constructor
    ///////////////////////////////////////////////////////////////////////////////////////////

    public PreferencesPayload() {
    }


    ///////////////////////////////////////////////////////////////////////////////////////////
    // PROTO BUFFER
    ///////////////////////////////////////////////////////////////////////////////////////////

    @Override
    public Message toProtoMessage() {
        PB.PreferencesPayload.Builder builder = PB.PreferencesPayload.newBuilder()
            .setUserLanguage(userLanguage)
            .setUserCountry((PB.Country) userCountry.toProtoMessage())
            .addAllFiatCurrencies(fiatCurrencies.stream()
                .map(fiatCurrency -> ((PB.TradeCurrency) fiatCurrency.toProtoMessage()))
                .collect(Collectors.toList()))
            .addAllCryptoCurrencies(cryptoCurrencies.stream()
                .map(cryptoCurrency -> ((PB.TradeCurrency) cryptoCurrency.toProtoMessage()))
                .collect(Collectors.toList()))
            .setBlockChainExplorerMainNet((PB.BlockChainExplorer) blockChainExplorerMainNet.toProtoMessage())
            .setBlockChainExplorerTestNet((PB.BlockChainExplorer) blockChainExplorerTestNet.toProtoMessage())
            .setBsqBlockChainExplorer((PB.BlockChainExplorer) bsqBlockChainExplorer.toProtoMessage())
            .setAutoSelectArbitrators(autoSelectArbitrators)
            .putAllDontShowAgainMap(dontShowAgainMap)
            .setTacAccepted(tacAccepted)
            .setUseTorForBitcoinJ(useTorForBitcoinJ)
            .setShowOwnOffersInOfferBook(showOwnOffersInOfferBook)
            .setWithdrawalTxFeeInBytes(withdrawalTxFeeInBytes)
            .setUseCustomWithdrawalTxFee(useCustomWithdrawalTxFee)
            .setMaxPriceDistanceInPercent(maxPriceDistanceInPercent)
            .setTradeStatisticsTickUnitIndex(tradeStatisticsTickUnitIndex)
            .setResyncSpvRequested(resyncSpvRequested)
            .setSortMarketCurrenciesNumerically(sortMarketCurrenciesNumerically)
            .setUsePercentageBasedPrice(usePercentageBasedPrice)
            .putAllPeerTagMap(peerTagMap)
            .setBitcoinNodes(bitcoinNodes)
            .addAllIgnoreTradersList(ignoreTradersList)
            .setDirectoryChooserPath(directoryChooserPath)
            .setBuyerSecurityDepositAsLong(buyerSecurityDepositAsLong)
            .setUseAnimations(useAnimations)
            .setPayFeeInBtc(payFeeInBtc)
            .addAllBridgeAddresses(bridgeAddresses);
        Optional.ofNullable(backupDirectory).ifPresent(builder::setBackupDirectory);
        Optional.ofNullable(preferredTradeCurrency).ifPresent(e -> builder.setPreferredTradeCurrency((PB.TradeCurrency) e.toProtoMessage()));
        Optional.ofNullable(offerBookChartScreenCurrencyCode).ifPresent(builder::setOfferBookChartScreenCurrencyCode);
        Optional.ofNullable(tradeChartsScreenCurrencyCode).ifPresent(builder::setTradeChartsScreenCurrencyCode);
        Optional.ofNullable(buyScreenCurrencyCode).ifPresent(builder::setBuyScreenCurrencyCode);
        Optional.ofNullable(sellScreenCurrencyCode).ifPresent(builder::setSellScreenCurrencyCode);
        Optional.ofNullable(selectedPaymentAccountForCreateOffer).ifPresent(
            account -> builder.setSelectedPaymentAccountForCreateOffer(selectedPaymentAccountForCreateOffer.toProtoMessage()));
        return PB.PersistableEnvelope.newBuilder().setPreferencesPayload(builder).build();
    }

    public static PersistableEnvelope fromProto(PB.PreferencesPayload proto, CoreProtoResolver coreProtoResolver) {
        final PB.Country userCountry = proto.getUserCountry();
        PaymentAccount paymentAccount = null;
        if (proto.hasSelectedPaymentAccountForCreateOffer() && proto.getSelectedPaymentAccountForCreateOffer().hasPaymentMethod())
            paymentAccount = PaymentAccount.fromProto(proto.getSelectedPaymentAccountForCreateOffer(), coreProtoResolver);

        return new PreferencesPayload(
                proto.getUserLanguage(),<commit_msg>Fixed the nullable bridgeAddresses proto handling<commit_after>package io.bisq.core.user;

import com.google.common.collect.Maps;
import com.google.protobuf.Message;
import io.bisq.common.locale.Country;
import io.bisq.common.locale.CryptoCurrency;
import io.bisq.common.locale.FiatCurrency;
import io.bisq.common.locale.TradeCurrency;
import io.bisq.common.proto.ProtoUtil;
import io.bisq.common.proto.persistable.PersistableEnvelope;
import io.bisq.core.btc.Restrictions;
import io.bisq.core.payment.PaymentAccount;
import io.bisq.core.proto.CoreProtoResolver;
import io.bisq.generated.protobuffer.PB;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Data
@AllArgsConstructor
public final class PreferencesPayload implements PersistableEnvelope {
    private String userLanguage;
    private Country userCountry;
    @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
    private List<FiatCurrency> fiatCurrencies = new ArrayList<>();
    @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
    private List<CryptoCurrency> cryptoCurrencies = new ArrayList<>();
    private BlockChainExplorer blockChainExplorerMainNet;
    private BlockChainExplorer blockChainExplorerTestNet;
    private BlockChainExplorer bsqBlockChainExplorer = Preferences.BSQ_MAIN_NET_EXPLORER;
    @Nullable
    private String backupDirectory;
    private boolean autoSelectArbitrators = true;
    private Map<String, Boolean> dontShowAgainMap = new HashMap<>();
    private boolean tacAccepted;
    private boolean useTorForBitcoinJ = true;
    private boolean showOwnOffersInOfferBook = true;
    @Nullable
    private TradeCurrency preferredTradeCurrency;
    private long withdrawalTxFeeInBytes = 100;
    private boolean useCustomWithdrawalTxFee = false;
    private double maxPriceDistanceInPercent = 0.1;
    @Nullable
    private String offerBookChartScreenCurrencyCode;
    @Nullable
    private String tradeChartsScreenCurrencyCode;
    @Nullable
    private String buyScreenCurrencyCode;
    @Nullable
    private String sellScreenCurrencyCode;
    private int tradeStatisticsTickUnitIndex = 3;
    private boolean resyncSpvRequested;
    private boolean sortMarketCurrenciesNumerically = true;
    private boolean usePercentageBasedPrice = true;
    private Map<String, String> peerTagMap = new HashMap<>();
    private String bitcoinNodes = "";
    private List<String> ignoreTradersList = new ArrayList<>();
    private String directoryChooserPath;
    private long buyerSecurityDepositAsLong = Restrictions.getDefaultBuyerSecurityDeposit().value;
    private boolean useAnimations;
    @Nullable
    private PaymentAccount selectedPaymentAccountForCreateOffer;
    private boolean payFeeInBtc = true;
    @Nullable
    private List<String> bridgeAddresses = new ArrayList<>();


    ///////////////////////////////////////////////////////////////////////////////////////////
    // Constructor
    ///////////////////////////////////////////////////////////////////////////////////////////

    public PreferencesPayload() {
    }


    ///////////////////////////////////////////////////////////////////////////////////////////
    // PROTO BUFFER
    ///////////////////////////////////////////////////////////////////////////////////////////

    @Override
    public Message toProtoMessage() {
        PB.PreferencesPayload.Builder builder = PB.PreferencesPayload.newBuilder()
            .setUserLanguage(userLanguage)
            .setUserCountry((PB.Country) userCountry.toProtoMessage())
            .addAllFiatCurrencies(fiatCurrencies.stream()
                .map(fiatCurrency -> ((PB.TradeCurrency) fiatCurrency.toProtoMessage()))
                .collect(Collectors.toList()))
            .addAllCryptoCurrencies(cryptoCurrencies.stream()
                .map(cryptoCurrency -> ((PB.TradeCurrency) cryptoCurrency.toProtoMessage()))
                .collect(Collectors.toList()))
            .setBlockChainExplorerMainNet((PB.BlockChainExplorer) blockChainExplorerMainNet.toProtoMessage())
            .setBlockChainExplorerTestNet((PB.BlockChainExplorer) blockChainExplorerTestNet.toProtoMessage())
            .setBsqBlockChainExplorer((PB.BlockChainExplorer) bsqBlockChainExplorer.toProtoMessage())
            .setAutoSelectArbitrators(autoSelectArbitrators)
            .putAllDontShowAgainMap(dontShowAgainMap)
            .setTacAccepted(tacAccepted)
            .setUseTorForBitcoinJ(useTorForBitcoinJ)
            .setShowOwnOffersInOfferBook(showOwnOffersInOfferBook)
            .setWithdrawalTxFeeInBytes(withdrawalTxFeeInBytes)
            .setUseCustomWithdrawalTxFee(useCustomWithdrawalTxFee)
            .setMaxPriceDistanceInPercent(maxPriceDistanceInPercent)
            .setTradeStatisticsTickUnitIndex(tradeStatisticsTickUnitIndex)
            .setResyncSpvRequested(resyncSpvRequested)
            .setSortMarketCurrenciesNumerically(sortMarketCurrenciesNumerically)
            .setUsePercentageBasedPrice(usePercentageBasedPrice)
            .putAllPeerTagMap(peerTagMap)
            .setBitcoinNodes(bitcoinNodes)
            .addAllIgnoreTradersList(ignoreTradersList)
            .setDirectoryChooserPath(directoryChooserPath)
            .setBuyerSecurityDepositAsLong(buyerSecurityDepositAsLong)
            .setUseAnimations(useAnimations)
            .setPayFeeInBtc(payFeeInBtc);
        Optional.ofNullable(bridgeAddresses).ifPresent(builder::addAllBridgeAddresses);
        Optional.ofNullable(backupDirectory).ifPresent(builder::setBackupDirectory);
        Optional.ofNullable(preferredTradeCurrency).ifPresent(e -> builder.setPreferredTradeCurrency((PB.TradeCurrency) e.toProtoMessage()));
        Optional.ofNullable(offerBookChartScreenCurrencyCode).ifPresent(builder::setOfferBookChartScreenCurrencyCode);
        Optional.ofNullable(tradeChartsScreenCurrencyCode).ifPresent(builder::setTradeChartsScreenCurrencyCode);
        Optional.ofNullable(buyScreenCurrencyCode).ifPresent(builder::setBuyScreenCurrencyCode);
        Optional.ofNullable(sellScreenCurrencyCode).ifPresent(builder::setSellScreenCurrencyCode);
        Optional.ofNullable(selectedPaymentAccountForCreateOffer).ifPresent(
            account -> builder.setSelectedPaymentAccountForCreateOffer(selectedPaymentAccountForCreateOffer.toProtoMessage()));
        return PB.PersistableEnvelope.newBuilder().setPreferencesPayload(builder).build();
    }

    public static PersistableEnvelope fromProto(PB.PreferencesPayload proto, CoreProtoResolver coreProtoResolver) {
        final PB.Country userCountry = proto.getUserCountry();
        PaymentAccount paymentAccount = null;
        if (proto.hasSelectedPaymentAccountForCreateOffer() && proto.getSelectedPaymentAccountForCreateOffer().hasPaymentMethod())
            paymentAccount = PaymentAccount.fromProto(proto.getSelectedPaymentAccountForCreateOffer(), coreProtoResolver);

        return new PreferencesPayload(
                proto.getUserLanguage(),
{'fraction_non_alphanumeric': 0.1241114586295138, 'fraction_numerical': 0.0012794995735001423, 'mean_word_length': 3.38696601184908, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4151891', 'n_tokens_mistral': 3672, 'n_tokens_neox': 3591, 'n_words': 550}