package com.tangem.ui.activity import android.app.Activity import android.content.Intent import android.content.res.ColorStateList import android.graphics.Color import android.media.MediaPlayer import android.nfc.NfcAdapter import android.nfc.Tag import android.nfc.tech.IsoDep import android.os.Bundle import android.view.KeyEvent import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.tangem.App import com.tangem.Constant import com.tangem.card_android.android.nfc.NfcDeviceAntennaLocation import com.tangem.card_android.android.nfc.NfcLifecycleObserver import com.tangem.card_android.android.reader.NfcManager import com.tangem.card_android.android.reader.NfcReader import com.tangem.card_android.data.EXTRA_TANGEM_CARD import com.tangem.card_android.data.EXTRA_TANGEM_CARD_UID import com.tangem.card_android.data.asBundle import com.tangem.card_common.reader.CardProtocol import com.tangem.card_common.tasks.SignTask import com.tangem.card_common.util.Util import com.tangem.ui.dialog.NoExtendedLengthSupportDialog import com.tangem.ui.dialog.WaitSecurityDelayDialog import com.tangem.util.LOG import com.tangem.wallet.CoinEngine import com.tangem.wallet.CoinEngineFactory import com.tangem.wallet.R import com.tangem.wallet.TangemContext import kotlinx.android.synthetic.main.layout_progress_horizontal.* import kotlinx.android.synthetic.main.layout_touch_card.* import kotlinx.android.synthetic.tangemAccess.activity_prepare_transaction.* class SignTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtocol.Notifications { companion object { val TAG: String = SignTransactionActivity::class.java.simpleName } private lateinit var nfcManager: NfcManager private lateinit var ctx: TangemContext private lateinit var mpFinishSignSound: MediaPlayer private lateinit var nfcDeviceAntenna: NfcDeviceAntennaLocation private var signTransactionTask: SignTask? = null private lateinit var amount: CoinEngine.Amount private lateinit var fee: CoinEngine.Amount private var isIncludeFee = true private var outAddressStr: String? = null private var lastReadSuccess = true override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_sign_transaction) nfcManager = NfcManager(this, this) lifecycle.addObserver(NfcLifecycleObserver(nfcManager)) ctx = TangemContext.loadFromBundle(this, intent.extras) mpFinishSignSound = MediaPlayer.create(this, R.raw.scan_card_sound) // init NFC Antenna nfcDeviceAntenna = NfcDeviceAntennaLocation(this, ivHandCardHorizontal, ivHandCardVertical, llHand, llNfc) nfcDeviceAntenna.init() amount = CoinEngine.Amount(intent.getStringExtra(Constant.EXTRA_AMOUNT), intent.getStringExtra(Constant.EXTRA_AMOUNT_CURRENCY)) fee = CoinEngine.Amount(intent.getStringExtra(Constant.EXTRA_FEE), intent.getStringExtra(Constant.EXTRA_FEE_CURRENCY)) isIncludeFee = intent.getBooleanExtra(Constant.EXTRA_FEE_INCLUDED, true) outAddressStr = intent.getStringExtra(Constant.EXTRA_TARGET_ADDRESS) tvCardID.text = ctx.card!!.cidDescription progressBar.progressTintList = ColorStateList.valueOf(Color.DKGRAY) progressBar.visibility = View.INVISIBLE } public override fun onPause() { signTransactionTask?.cancel(true) super.onPause() } public override fun onStop() { signTransactionTask?.cancel(true) super.onStop() } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == Constant.REQUEST_CODE_SEND_TRANSACTION_) { setResult(resultCode, data) finish() return } super.onActivityResult(requestCode, resultCode, data) } override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { when (keyCode) { KeyEvent.KEYCODE_BACK -> { val intent = Intent() setResult(Activity.RESULT_CANCELED, intent) finish() return true } } return super.onKeyDown(keyCode, event) } override fun onTagDiscovered(tag: Tag) { try { // get IsoDep handle and run cardReader thread val isoDep = IsoDep.get(tag) val uid = tag.id val sUID = Util.byteArrayToHexString(uid) if (sUID == ctx.card.uid) { if (lastReadSuccess) isoDep.timeout = ctx.card.pauseBeforePIN2 + 5000 else isoDep.timeout = ctx.card.pauseBeforePIN2 + 65000 val coinEngine = CoinEngineFactory.create(ctx) coinEngine?.setOnNeedSendTransaction { tx -> if (tx != null) { val intent = Intent(this, SendTransactionActivity::class.java) ctx.saveToIntent(intent) intent.putExtra(Constant.EXTRA_TX, tx) startActivityForResult(intent, Constant.REQUEST_CODE_SEND_TRANSACTION_) } } val transactionToSign = coinEngine?.constructTransaction(amount, fee, isIncludeFee, outAddressStr) signTransactionTask = SignTask(ctx.card, NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, this, transactionToSign) signTransactionTask?.start() } else nfcManager.ignoreTag(isoDep.tag) } catch (e: CardProtocol.TangemException_WrongAmount) { try { val intent = Intent() intent.putExtra(Constant.EXTRA_MESSAGE, getString(R.string.send_transaction_error_wrong_amount)) intent.putExtra(EXTRA_TANGEM_CARD_UID, ctx.card.uid) intent.putExtra(EXTRA_TANGEM_CARD, ctx.card.asBundle) setResult(Activity.RESULT_CANCELED, intent) finish() } catch (e: Exception) { e.printStackTrace() } } catch (e: Exception) { e.printStackTrace() } } override fun onReadStart(cardProtocol: CardProtocol) { rlProgressBar.post { rlProgressBar.visibility = View.VISIBLE } progressBar?.post { progressBar?.visibility = View.VISIBLE progressBar?.progress = 5 } } override fun onReadProgress(protocol: CardProtocol, progress: Int) { progressBar?.post { progressBar!!.progress = progress } } override fun onReadFinish(cardProtocol: CardProtocol?) { signTransactionTask = null if (cardProtocol != null) { if (cardProtocol.error == null) { rlProgressBar.post { rlProgressBar.visibility = View.GONE } progressBar?.post { progressBar?.progress = 100 progressBar?.progressTintList = ColorStateList.valueOf(Color.GREEN) } mpFinishSignSound.start() } else { lastReadSuccess = false if (cardProtocol.error.javaClass == CardProtocol.TangemException_InvalidPIN::class.java) { progressBar?.post { progressBar?.progress = 100 progressBar?.progressTintList = ColorStateList.valueOf(Color.RED) } progressBar?.postDelayed({ try { progressBar?.progress = 0 progressBar?.progressTintList = ColorStateList.valueOf(Color.DKGRAY) progressBar?.visibility = View.INVISIBLE val intent = Intent() intent.putExtra(Constant.EXTRA_MESSAGE, getString(R.string.send_transaction_error_cannot_sign)) intent.putExtra(EXTRA_TANGEM_CARD_UID, cardProtocol.card.uid) intent.putExtra(EXTRA_TANGEM_CARD, cardProtocol.card.asBundle) setResult(Constant.RESULT_INVALID_PIN_, intent) finish() } catch (e: Exception) { e.printStackTrace() } }, 500) } else { if (cardProtocol.error is CardProtocol.TangemException_WrongAmount) { try { val intent = Intent() intent.putExtra(Constant.EXTRA_MESSAGE, getString(R.string.send_transaction_error_wrong_amount)) intent.putExtra(EXTRA_TANGEM_CARD_UID, cardProtocol.card.uid) intent.putExtra(EXTRA_TANGEM_CARD, cardProtocol.card.asBundle) setResult(Activity.RESULT_CANCELED, intent) finish() } catch (e: Exception) { e.printStackTrace() } } progressBar?.post { if (cardProtocol.error is CardProtocol.TangemException_ExtendedLengthNotSupported) { if (!NoExtendedLengthSupportDialog.allReadyShowed) { NoExtendedLengthSupportDialog.message = getText(R.string.dialog_the_nfc_adapter_length_apdu).toString() + "\n" + getText(R.string.dialog_the_nfc_adapter_length_apdu_advice).toString() NoExtendedLengthSupportDialog().show(supportFragmentManager, NoExtendedLengthSupportDialog.TAG) } } else { Toast.makeText(baseContext, R.string.general_notification_scan_again, Toast.LENGTH_LONG).show() } progressBar?.progress = 100 progressBar?.progressTintList = ColorStateList.valueOf(Color.RED) } } } } rlProgressBar.postDelayed({ try { rlProgressBar.visibility = View.GONE } catch (e: Exception) { e.printStackTrace() } }, 500) progressBar?.postDelayed({ try { progressBar?.progress = 0 progressBar?.progressTintList = ColorStateList.valueOf(Color.DKGRAY) progressBar?.visibility = View.INVISIBLE } catch (e: Exception) { e.printStackTrace() } }, 500) } override fun onReadCancel() { signTransactionTask = null progressBar?.postDelayed({ try { progressBar?.progress = 0 progressBar?.progressTintList = ColorStateList.valueOf(Color.DKGRAY) progressBar?.visibility = View.INVISIBLE } catch (e: Exception) { e.printStackTrace() } }, 500) } // private val waitSecurityDelayDialogNew = WaitSecurityDelayDialogNew() override fun onReadBeforeRequest(timeout: Int) { LOG.i(TAG, "onReadBeforeRequest timeout $timeout") WaitSecurityDelayDialog.onReadBeforeRequest(this, timeout) // if (!waitSecurityDelayDialogNew.isAdded) // waitSecurityDelayDialogNew.show(supportFragmentManager, WaitSecurityDelayDialogNew.TAG) // val readBeforeRequest = ReadBeforeRequest() // readBeforeRequest.timeout = timeout // EventBus.getDefault().post(readBeforeRequest) } override fun onReadAfterRequest() { LOG.i(TAG, "onReadAfterRequest") WaitSecurityDelayDialog.onReadAfterRequest(this) // val readAfterRequest = ReadAfterRequest() // EventBus.getDefault().post(readAfterRequest) } override fun onReadWait(msec: Int) { LOG.i(TAG, "onReadWait msec $msec") WaitSecurityDelayDialog.onReadWait(this, msec) // val readWait = ReadWait() // readWait.msec = msec // EventBus.getDefault().post(readWait) } }