/*
 * 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.desktop.main.dao.wallet.tx;

import bisq.desktop.components.TxConfidenceListItem;

import bisq.core.btc.wallet.BsqWalletService;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.WalletService;
import bisq.core.dao.DaoFacade;
import bisq.core.dao.state.model.blockchain.TxType;
import bisq.core.locale.Res;
import bisq.core.util.coin.BsqFormatter;

import org.bitcoinj.core.Coin;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionOutput;

import java.util.Date;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import static com.google.common.base.Preconditions.checkNotNull;

@Slf4j
@EqualsAndHashCode(callSuper = true)
@Getter
class BsqTxListItem extends TxConfidenceListItem {
    private final DaoFacade daoFacade;
    private final BsqFormatter bsqFormatter;
    private final Date date;
    private final boolean isBurnedBsqTx;
    private final boolean withdrawalToBTCWallet;

    private final String address;
    private final String direction;
    private final Coin amount;
    private boolean received;

    BsqTxListItem(Transaction transaction,
                  BsqWalletService bsqWalletService,
                  BtcWalletService btcWalletService,
                  DaoFacade daoFacade,
                  Date date,
                  BsqFormatter bsqFormatter) {
        super(transaction, bsqWalletService);

        this.daoFacade = daoFacade;
        this.isBurnedBsqTx = daoFacade.hasTxBurntFee(transaction.getTxId().toString());
        this.date = date;
        this.bsqFormatter = bsqFormatter;

        checkNotNull(transaction, "transaction must not be null as we only have list items from transactions " +
                "which are available in the wallet");

        Coin valueSentToMe = bsqWalletService.getValueSentToMeForTransaction(transaction);
        Coin valueSentFromMe = bsqWalletService.getValueSentFromMeForTransaction(transaction);
        Coin valueSentToMyBTCWallet = btcWalletService.getValueSentToMeForTransaction(transaction);
        Coin valueSentFromMyBTCWallet = btcWalletService.getValueSentFromMeForTransaction(transaction);

        withdrawalToBTCWallet = valueSentToMyBTCWallet.getValue() > valueSentFromMyBTCWallet.getValue();

        amount = valueSentToMe.subtract(valueSentFromMe);
        if (amount.isPositive()) {
            if (txId.equals(daoFacade.getGenesisTxId()))
                direction = Res.get("funds.tx.direction.genesisTx");
            else
                direction = Res.get("funds.tx.direction.receivedWith");

            received = true;
        } else if (amount.isNegative()) {
            direction = Res.get("funds.tx.direction.sentTo");
            received = false;
        } else {
            // Self send
            direction = "";
        }

        String sendToAddress = null;
        for (TransactionOutput output : transaction.getOutputs()) {
            if (!bsqWalletService.isTransactionOutputMine(output) &&
                    !btcWalletService.isTransactionOutputMine(output) &&
                    WalletService.isOutputScriptConvertibleToAddress(output)) {
                // We don't support send txs with multiple outputs to multiple receivers, so we can
                // assume that only one output is not from our own wallets.
                LegacyAddress addressFromOutput = (LegacyAddress) WalletService.getAddressFromOutput(output);
                if (addressFromOutput != null) {
                    sendToAddress = bsqFormatter.getBsqAddressStringFromAddress(addressFromOutput);
                }
                break;
            }
        }

        // In the case we sent to ourselves (either to BSQ or BTC wallet) we show the first as the other is
        // usually the change output.
        String receivedWithAddress = Res.get("shared.na");
        if (sendToAddress != null) {
            for (TransactionOutput output : transaction.getOutputs()) {
                if (WalletService.isOutputScriptConvertibleToAddress(output)) {
                    LegacyAddress addressFromOutput = (LegacyAddress) WalletService.getAddressFromOutput(output);
                    if (addressFromOutput != null) {
                        receivedWithAddress = bsqFormatter.getBsqAddressStringFromAddress(addressFromOutput);
                    }
                    break;
                }
            }
        }

        if (!isBurnedBsqTx)
            address = received ? receivedWithAddress : sendToAddress;
        else
            address = "";
    }

    public TxType getTxType() {
        return daoFacade.getTx(txId)
                .flatMap(tx -> daoFacade.getOptionalTxType(tx.getId()))
                .orElse(confirmations == 0 ? TxType.UNVERIFIED : TxType.UNDEFINED_TX_TYPE);
    }

    public boolean isWithdrawalToBTCWallet() {
        return withdrawalToBTCWallet;
    }
}


@@ -1061,16 +1061,50 @@
 atter;%0A%0A
+import org.bitcoinj.core.Address;%0A
 import o
@@ -4101,38 +4101,76 @@
                 
-Legacy
+// We ignore segwit outputs%0A                
 Address addressF
@@ -4180,32 +4180,16 @@
 Output =
- (LegacyAddress)
  WalletS
@@ -4255,39 +4255,56 @@
 dressFromOutput 
-!= null
+instanceof LegacyAddress
 ) %7B%0A            
@@ -4363,32 +4363,48 @@
 ringFromAddress(
+(LegacyAddress) 
 addressFromOutpu
@@ -4415,33 +4415,42 @@
                 
-%7D
+    break;
 %0A               
@@ -4442,38 +4442,33 @@
                 
-break;
+%7D
 %0A            %7D%0A 
@@ -4686,49 +4686,8 @@
 %22);%0A
-        if (sendToAddress != null) %7B%0A    
     
@@ -4742,36 +4742,32 @@
 getOutputs()) %7B%0A
-    
             if (
@@ -4846,18 +4846,8 @@
     
-    
-Legacy
 Addr
@@ -4873,24 +4873,8 @@
 ut =
- (LegacyAddress)
  Wal
@@ -4915,32 +4915,67 @@
 tput);%0A         
+       // We ignore segwit outputs%0A
            if (a
@@ -4961,32 +4961,37 @@
 puts%0A           
+     
 if (addressFromO
@@ -5000,23 +5000,36 @@
 put 
-!= null) %7B%0A    
+instanceof LegacyAddress) %7B%0A
     
@@ -5110,16 +5110,32 @@
 Address(
+(LegacyAddress) 
 addressF
@@ -5150,30 +5150,8 @@
 t);%0A
-                    %7D%0A
     

Check if output is a legacy address. Remove `sendToAddress != null` check.