package cash.z.ecc.android.ui.setup
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.Toast
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import cash.z.ecc.android.R
import cash.z.ecc.android.ZcashWalletApp
import cash.z.ecc.android.databinding.FragmentLandingBinding
import cash.z.ecc.android.ext.locale
import cash.z.ecc.android.ext.showSharedLibraryCriticalError
import cash.z.ecc.android.ext.toAppString
import cash.z.ecc.android.feedback.Report
import cash.z.ecc.android.feedback.Report.Funnel.Restore
import cash.z.ecc.android.feedback.Report.Tap.*
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.android.ui.base.BaseFragment
import cash.z.ecc.android.ui.setup.WalletSetupViewModel.WalletSetupState.SEED_WITHOUT_BACKUP
import cash.z.ecc.android.ui.setup.WalletSetupViewModel.WalletSetupState.SEED_WITH_BACKUP
import cash.z.ecc.android.util.twig
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
class LandingFragment : BaseFragment < FragmentLandingBinding > ( ) {
override val screen = Report . Screen . LANDING
private val walletSetup : WalletSetupViewModel by activityViewModels ( )
private var skipCount : Int = 0
override fun inflate ( inflater : LayoutInflater ) : FragmentLandingBinding =
FragmentLandingBinding . inflate ( inflater )
override fun onViewCreated ( view : View , savedInstanceState : Bundle ? ) {
super . onViewCreated ( view , savedInstanceState )
binding . buttonPositive . setOnClickListener {
when ( binding . buttonPositive . text . toString ( ) . toLowerCase ( locale ( ) ) ) {
R . string . landing_button_primary . toAppString ( true ) -> onNewWallet ( ) . also {
tapped (
LANDING_NEW
)
}
R . string . landing_button_primary_create_success . toAppString ( true ) -> onBackupWallet ( ) . also {
tapped (
LANDING_BACKUP
)
}
}
}
binding . buttonNegative . setOnLongClickListener {
tapped ( DEVELOPER_WALLET_PROMPT )
if ( binding . buttonNegative . text . toString ( ) . toLowerCase ( locale ( ) ) == " restore " ) {
MaterialAlertDialogBuilder ( requireContext ( ) )
. setMessage ( " Would you like to import the dev wallet? \n \n If so, please only send 1000 puposhis at a time and return some later so that the account remains funded. Or be greedy and steal it all. Nobody will know it was you :) " )
. setTitle ( " Import Dev Wallet? " )
. setCancelable ( true )
. setPositiveButton ( " Import " ) { dialog , _ ->
tapped ( DEVELOPER_WALLET_IMPORT )
dialog . dismiss ( )
onUseDevWallet ( )
}
. setNegativeButton ( " Cancel " ) { dialog , _ ->
tapped ( DEVELOPER_WALLET_CANCEL )
dialog . dismiss ( )
}
. show ( )
true
} else {
false
}
}
binding . buttonNegative . setOnClickListener {
when ( binding . buttonNegative . text . toString ( ) . toLowerCase ( locale ( ) ) ) {
R . string . landing_button_secondary . toAppString ( true ) -> onRestoreWallet ( ) . also {
mainActivity ?. reportFunnel ( Restore . Initiated )
tapped ( LANDING_RESTORE )
}
else -> onSkip ( ++ skipCount )
}
}
}
override fun onAttach ( context : Context ) {
super . onAttach ( context )
walletSetup . checkSeed ( ) . onEach {
when ( it ) {
SEED_WITHOUT_BACKUP , SEED_WITH_BACKUP -> {
mainActivity ?. safeNavigate ( R . id . nav_backup )
}
else -> { }
}
} . launchIn ( lifecycleScope )
}
override fun onResume ( ) {
super . onResume ( )
view ?. postDelayed (
{
mainActivity ?. hideKeyboard ( )
} ,
25L
)
}
private fun onSkip ( count : Int ) {
when ( count ) {
1 -> {
tapped ( LANDING_BACKUP_SKIPPED_1 )
binding . textMessage . setText ( R . string . landing_backup_skipped_message_1 )
binding . buttonNegative . setText ( R . string . landing_button_backup_skipped_1 )
}
2 -> {
tapped ( LANDING_BACKUP_SKIPPED_2 )
binding . textMessage . setText ( R . string . landing_backup_skipped_message_2 )
binding . buttonNegative . setText ( R . string . landing_button_backup_skipped_2 )
}
else -> {
tapped ( LANDING_BACKUP_SKIPPED_3 )
onEnterWallet ( )
}
}
}
private fun onRestoreWallet ( ) {
mainActivity ?. safeNavigate ( R . id . action_nav_landing_to_nav_restore )
}
// AKA import wallet
private fun onUseDevWallet ( ) {
val seedPhrase : String
val birthday : BlockHeight
// new testnet dev wallet
when ( ZcashWalletApp . instance . defaultNetwork ) {
ZcashNetwork . Mainnet -> {
seedPhrase =
" still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread "
birthday = BlockHeight . new ( ZcashNetwork . Mainnet , 1270000 )
}
ZcashNetwork . Testnet -> {
seedPhrase =
" quantum whisper lion route fury lunar pelican image job client hundred sauce chimney barely life cliff spirit admit weekend message recipe trumpet impact kitten "
birthday = BlockHeight . new ( ZcashNetwork . Testnet , 1330190 )
}
else -> throw RuntimeException ( " No developer wallet exists for network ${ZcashWalletApp.instance.defaultNetwork} " )
}
mainActivity ?. apply {
lifecycleScope . launch {
try {
walletSetup . importWallet ( seedPhrase , birthday )
mainActivity ?. startSync ( )
binding . buttonPositive . isEnabled = true
binding . textMessage . setText ( R . string . landing_import_success_message )
binding . buttonNegative . setText ( R . string . landing_button_secondary_import_success )
binding . buttonPositive . setText ( R . string . landing_import_success_primary_button )
playSound ( " sound_receive_small.mp3 " )
vibrateSuccess ( )
} catch ( e : UnsatisfiedLinkError ) {
mainActivity ?. showSharedLibraryCriticalError ( e )
}
}
}
}
private fun onNewWallet ( ) {
lifecycleScope . launch {
binding . buttonPositive . setText ( R . string . landing_button_progress_create )
binding . buttonPositive . isEnabled = false
try {
walletSetup . newWallet ( )
mainActivity ?. startSync ( )
binding . buttonPositive . isEnabled = true
binding . textMessage . setText ( R . string . landing_create_success_message )
binding . buttonNegative . setText ( R . string . landing_button_secondary_create_success )
binding . buttonPositive . setText ( R . string . landing_button_primary_create_success )
mainActivity ?. playSound ( " sound_receive_small.mp3 " )
mainActivity ?. vibrateSuccess ( )
} catch ( e : UnsatisfiedLinkError ) {
// For developer sanity:
// show a nice dialog, rather than a toast, when the rust didn't get compile
// which can happen often when working from a local SDK build
mainActivity ?. showSharedLibraryCriticalError ( e )
} catch ( t : Throwable ) {
twig ( " Failed to create wallet due to: $t " )
mainActivity ?. feedback ?. report ( t )
binding . buttonPositive . isEnabled = true
binding . buttonPositive . setText ( R . string . landing_button_primary )
Toast . makeText (
context ,
" Failed to create wallet. See logs for details. Try restarting the app. \n \n Message: \n ${t.message} " ,
Toast . LENGTH_LONG
) . show ( )
}
}
}
private fun onBackupWallet ( ) {
skipCount = 0
mainActivity ?. safeNavigate ( R . id . action_nav_landing_to_nav_backup )
}
private fun onEnterWallet ( ) {
skipCount = 0
mainActivity ?. navController ?. popBackStack ( )
}
}