package mockengine

import (
	"github.com/ethereum/go-ethereum/common"
	nebulav1 "github.com/exchain/go-exchain/exchain/protocol/gen/go/nebula/v1"
	"github.com/exchain/go-exchain/exchain/wrapper"
	"github.com/holiman/uint256"
	log "github.com/sirupsen/logrus"
)

func (m MockEngine) ProcessTx(header *nebulav1.BlockHeader, txs *nebulav1.TransactionList) (*nebulav1.TransactionReceiptList, error) {
	receipts := &nebulav1.TransactionReceiptList{
		Receipts: make([]*nebulav1.TransactionReceipt, 0),
	}
	for _, tx := range txs.Txs {
		wtx := wrapper.NewTxWrapper(tx)
		receipt := &nebulav1.TransactionReceipt{
			Hash:        wtx.Hash().Bytes(),
			TxType:      tx.TxType,
			Success:     true,
			BlockHeight: header.Height,
			Timestamp:   header.Timestamp,
		}
		switch tx.TxType {
		case nebulav1.TxType_DepositTx:
			receipt.Content = &nebulav1.TransactionReceipt_DepositR{
				DepositR: &nebulav1.DepositReceipt{},
			}
			deposit := tx.GetDepositTx()
			log.WithFields(log.Fields{
				"from":  common.BytesToAddress(deposit.User),
				"coin":  string(deposit.Coin),
				"value": new(uint256.Int).SetBytes(deposit.Amount).String(),
			}).Info("Process deposit tx")
		case nebulav1.TxType_LimitTx:
			receipt.Content = &nebulav1.TransactionReceipt_LimitR{
				LimitR: &nebulav1.LimitOrderReceipt{},
			}
		case nebulav1.TxType_WithdrawTx:
			receipt.Content = &nebulav1.TransactionReceipt_WithdrawR{
				WithdrawR: &nebulav1.WithdrawReceipt{},
			}
		case nebulav1.TxType_CancelTx:
			receipt.Content = &nebulav1.TransactionReceipt_CancelR{
				CancelR: &nebulav1.CancelOrderReceipt{},
			}
		case nebulav1.TxType_MarketTx:
			receipt.Content = &nebulav1.TransactionReceipt_MarketR{
				MarketR: &nebulav1.MarketOrderReceipt{},
			}
		case nebulav1.TxType_CreatePairTx:
			receipt.Content = &nebulav1.TransactionReceipt_CreatePairR{
				CreatePairR: &nebulav1.CreatePairReceipt{},
			}
		case nebulav1.TxType_DisablePairTx:
			receipt.Content = &nebulav1.TransactionReceipt_DisablePairR{
				DisablePairR: &nebulav1.DisablePairReceipt{},
			}
		case nebulav1.TxType_ProtocolTx:
			receipt.Content = &nebulav1.TransactionReceipt_ProtocolR{
				ProtocolR: &nebulav1.ProtocolTransactionReceipt{},
			}
		case nebulav1.TxType_SignProxyTx:
			receipt.Content = &nebulav1.TransactionReceipt_SignProxyR{
				SignProxyR: &nebulav1.SignProxyReceipt{},
			}
		default:
			// TODO: return error
		}
		receipts.Receipts = append(receipts.Receipts, receipt)
	}
	return receipts, nil
}
