import 'package:cake_wallet/core/open_crypto_pay/open_cryptopay_service.dart';
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
import 'package:cake_wallet/src/screens/receive/widgets/currency_input_field.dart';
import 'package:cake_wallet/src/widgets/picker.dart';
import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/currency.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/view_model/send/output.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/unspent_coin_type.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/view_model/send/send_view_model.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/src/widgets/address_text_field.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';

class SendCard extends StatefulWidget {
  SendCard({
    Key? key,
    required this.output,
    required this.sendViewModel,
    required this.currentTheme,
    this.initialPaymentRequest,
    this.cryptoAmountFocus,
    this.fiatAmountFocus,
  }) : super(key: key);

  final Output output;
  final SendViewModel sendViewModel;
  final PaymentRequest? initialPaymentRequest;
  final FocusNode? cryptoAmountFocus;
  final FocusNode? fiatAmountFocus;
  final ThemeBase currentTheme;


  @override
  SendCardState createState() => SendCardState(
        output: output,
        sendViewModel: sendViewModel,
        initialPaymentRequest: initialPaymentRequest,
        currentTheme: currentTheme
        // cryptoAmountFocus: cryptoAmountFocus ?? FocusNode(),
        // fiatAmountFocus: fiatAmountFocus ?? FocusNode(),
        // cryptoAmountFocus: FocusNode(),
        // fiatAmountFocus: FocusNode(),
      );
}

class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<SendCard> {
  SendCardState({
    required this.output,
    required this.sendViewModel,
    this.initialPaymentRequest,
    required this.currentTheme,
  })  : addressController = TextEditingController(),
        cryptoAmountController = TextEditingController(),
        fiatAmountController = TextEditingController(),
        noteController = TextEditingController(),
        extractedAddressController = TextEditingController(),
        addressFocusNode = FocusNode();

  static const prefixIconWidth = 34.0;
  static const prefixIconHeight = 34.0;

  final ThemeBase currentTheme;
  final Output output;
  final SendViewModel sendViewModel;
  final PaymentRequest? initialPaymentRequest;

  final TextEditingController addressController;
  final TextEditingController cryptoAmountController;
  final TextEditingController fiatAmountController;
  final TextEditingController noteController;
  final TextEditingController extractedAddressController;
  final FocusNode addressFocusNode;

  bool _effectsInstalled = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      sendViewModel.updateSendingBalance();
    });

    /// if the current wallet doesn't match the one in the qr code
    if (initialPaymentRequest != null &&
        sendViewModel.walletCurrencyName != initialPaymentRequest!.scheme.toLowerCase()) {
      WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
        if (mounted) {
          showPopUp<void>(
              context: context,
              builder: (BuildContext context) {
                return AlertWithOneAction(
                    alertTitle: S.of(context).error,
                    alertContent: S.of(context).unmatched_currencies,
                    buttonText: S.of(context).ok,
                    buttonAction: () => Navigator.of(context).pop());
              });
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    _setEffects(context);

    // return Stack(
    //   children: [
    // return KeyboardActions(
    //   config: KeyboardActionsConfig(
    //     keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
    //     keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
    //     nextFocus: false,
    //     actions: [
    //       KeyboardActionsItem(
    //         focusNode: cryptoAmountFocus,
    //         toolbarButtons: [(_) => KeyboardDoneButton()],
    //       ),
    //       KeyboardActionsItem(
    //         focusNode: fiatAmountFocus,
    //         toolbarButtons: [(_) => KeyboardDoneButton()],
    //       )
    //     ],
    //   ),
    //   // child: Container(
    //   //   height: 0,
    //   //   color: Colors.transparent,
    //   // ),      child:
    //   child: SizedBox(
    //     height: 100,
    //     width: 100,
    //     child: Text('Send Card'),
    //   ),
    // );
    return Container(
      decoration: responsiveLayoutUtil.shouldRenderMobileUI
          ? BoxDecoration(
              borderRadius: BorderRadius.only(
                  bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
              gradient: LinearGradient(
                colors: [
                  Theme.of(context).extension<SendPageTheme>()!.firstGradientColor,
                  Theme.of(context).extension<SendPageTheme>()!.secondGradientColor,
                ],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              ),
            )
          : null,
      child: Padding(
        padding: EdgeInsets.fromLTRB(
          24,
          responsiveLayoutUtil.shouldRenderMobileUI ? 110 : 55,
          24,
          responsiveLayoutUtil.shouldRenderMobileUI ? 32 : 0,
        ),
        child: Observer(
          builder: (_) => Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Observer(builder: (_) {
                final validator = output.isParsedAddress
                    ? sendViewModel.textValidator
                    : sendViewModel.addressValidator;

                return AddressTextField(
                  addressKey: ValueKey('send_page_address_textfield_key'),
                  focusNode: addressFocusNode,
                  controller: addressController,
                  onURIScanned: (uri) async {
                    if (OpenCryptoPayService.isOpenCryptoPayQR(
                        uri.toString())) {
                      sendViewModel.createOpenCryptoPayTransaction(uri.toString());
                    } else {
                      final paymentRequest = PaymentRequest.fromUri(uri);
                      addressController.text = paymentRequest.address;
                      cryptoAmountController.text = paymentRequest.amount;
                      noteController.text = paymentRequest.note;
                    }
                  },
                  options: [
                    AddressTextFieldOption.paste,
                    AddressTextFieldOption.qrCode,
                    AddressTextFieldOption.addressBook
                  ],
                  buttonColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
                  borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
                  textStyle:
                      TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
                  hintStyle: TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.w500,
                      color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
                  onPushPasteButton: (context) async {
                    output.resetParsedAddress();
                    await output.fetchParsedAddress(context);
                  },
                  onPushAddressBookButton: (context) async {
                    output.resetParsedAddress();
                  },
                  onSelectedContact: (contact) {
                    output.loadContact(contact);
                  },
                  validator: validator,
                  selectedCurrency: sendViewModel.selectedCryptoCurrency,
                );
              }),
              if (output.isParsedAddress)
                Padding(
                    padding: const EdgeInsets.only(top: 20),
                    child: BaseTextFormField(
                        controller: extractedAddressController,
                        readOnly: true,
                        borderColor:
                            Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
                        textStyle: TextStyle(
                            fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
                        validator: sendViewModel.addressValidator)),
              CurrencyAmountTextField(
                  currencyPickerButtonKey: ValueKey('send_page_currency_picker_button_key'),
                  amountTextfieldKey: ValueKey('send_page_amount_textfield_key'),
                  sendAllButtonKey: ValueKey('send_page_send_all_button_key'),
                  currencyAmountTextFieldWidgetKey:
                      ValueKey('send_page_crypto_currency_amount_textfield_widget_key'),
                  selectedCurrency: sendViewModel.selectedCryptoCurrency.title,
                  amountFocusNode: widget.cryptoAmountFocus,
                  amountController: cryptoAmountController,
                  isAmountEditable: true,
                  onTapPicker: () => _presentPicker(context),
                  isPickerEnable: sendViewModel.hasMultipleTokens,
                  tag: sendViewModel.selectedCryptoCurrency.tag,
                  allAmountButton:
                      !sendViewModel.isBatchSending && sendViewModel.shouldDisplaySendALL,
                  currencyValueValidator: output.sendAll
                      ? sendViewModel.allAmountValidator
                      : sendViewModel.amountValidator,
                  allAmountCallback: () async => output.setSendAll(await sendViewModel.sendingBalance)),
              Divider(
                  height: 1,
                  color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
              Observer(
                builder: (_) {
                  // force rebuild on mobx
                  final _ = sendViewModel.coinTypeToSpendFrom;
                  return Padding(
                    padding: EdgeInsets.only(top: 10),
                    child: Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        Expanded(
                          child: Text(
                            S.of(context).available_balance + ':',
                            style: TextStyle(
                                fontSize: 12,
                                fontWeight: FontWeight.w600,
                                color:
                                    Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
                          ),
                        ),
                        FutureBuilder<String>(
                          future: sendViewModel.sendingBalance,
                          builder: (context, snapshot) {
                            return Text(
                              snapshot.data ?? sendViewModel.balance, // default to balance while loading
                              style: TextStyle(
                              fontSize: 12,
                              fontWeight: FontWeight.w600,
                              color:
                                  Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
                            );
                          },
                        )
                      ],
                    ),
                  );
                },
              ),
              if (!sendViewModel.isFiatDisabled)
                CurrencyAmountTextField(
                    amountTextfieldKey: ValueKey('send_page_fiat_amount_textfield_key'),
                    currencyAmountTextFieldWidgetKey:
                        ValueKey('send_page_fiat_currency_amount_textfield_widget_key'),
                    selectedCurrency: sendViewModel.fiat.title,
                    amountFocusNode: widget.fiatAmountFocus,
                    amountController: fiatAmountController,
                    hintText: '0.00',
                    isAmountEditable: true,
                    allAmountButton: false),
              Divider(
                  height: 1,
                  color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
              Padding(
                padding: EdgeInsets.only(top: 20),
                child: BaseTextFormField(
                  key: ValueKey('send_page_note_textfield_key'),
                  controller: noteController,
                  keyboardType: TextInputType.multiline,
                  maxLines: null,
                  borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
                  textStyle:
                      TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
                  hintText: S.of(context).note_optional,
                  placeholderTextStyle: TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.w500,
                      color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
                ),
              ),
              if (sendViewModel.feesViewModel.hasFees)
                Observer(
                  builder: (_) => GestureDetector(
                    key: ValueKey('send_page_select_fee_priority_button_key'),
                    onTap: sendViewModel.feesViewModel.hasFeesPriority
                        ? () => pickTransactionPriority(context)
                        : () {},
                    child: Container(
                      padding: EdgeInsets.only(top: 24),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Text(
                            S.of(context).send_estimated_fee,
                            style: TextStyle(
                                fontSize: 12, fontWeight: FontWeight.w500, color: Colors.white),
                          ),
                          Container(
                            child: Row(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: <Widget>[
                                Column(
                                  mainAxisAlignment: MainAxisAlignment.start,
                                  crossAxisAlignment: CrossAxisAlignment.end,
                                  children: [
                                    Text(
                                      output.estimatedFee.toString() +
                                          ' ' +
                                          sendViewModel.currency.toString(),
                                      style: TextStyle(
                                        fontSize: 12,
                                        fontWeight: FontWeight.w600,
                                        color: Colors.white,
                                      ),
                                    ),
                                    Padding(
                                      padding: EdgeInsets.only(top: 5),
                                      child: sendViewModel.isFiatDisabled
                                          ? const SizedBox(height: 14)
                                          : Text(
                                              output.estimatedFeeFiatAmount +
                                                  ' ' +
                                                  sendViewModel.fiat.title,
                                              style: TextStyle(
                                                fontSize: 12,
                                                fontWeight: FontWeight.w600,
                                                color: Theme.of(context)
                                                    .extension<SendPageTheme>()!
                                                    .textFieldHintColor,
                                              ),
                                            ),
                                    ),
                                  ],
                                ),
                                Padding(
                                  padding: EdgeInsets.only(top: 2, left: 5),
                                  child: Icon(
                                    Icons.arrow_forward_ios,
                                    size: 12,
                                    color: Colors.white,
                                  ),
                                )
                              ],
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                ),
              if (sendViewModel.hasCoinControl)
                Padding(
                  padding: EdgeInsets.only(top: 6),
                  child: GestureDetector(
                    key: ValueKey('send_page_unspent_coin_button_key'),
                    onTap: () async {
                      await Navigator.of(context).pushNamed(
                        Routes.unspentCoinsList,
                        arguments: widget.sendViewModel.coinTypeToSpendFrom,
                      );
                      if (mounted) {
                        // we just got back from the unspent coins list screen, so we need to recompute the sending balance:
                        sendViewModel.updateSendingBalance();
                      }
                    },
                    child: Container(
                      color: Colors.transparent,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Text(
                            S.of(context).coin_control,
                            style: TextStyle(
                                fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white),
                          ),
                          Icon(
                            Icons.arrow_forward_ios,
                            size: 12,
                            color: Colors.white,
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              if (sendViewModel.currency == CryptoCurrency.ltc)
                Observer(
                  builder: (_) => Padding(
                    padding: EdgeInsets.only(top: 14),
                    child: GestureDetector(
                      key: ValueKey('send_page_unspent_coin_button_key'),
                      onTap: () {
                        bool value =
                            widget.sendViewModel.coinTypeToSpendFrom == UnspentCoinType.any;
                        sendViewModel.setAllowMwebCoins(!value);
                      },
                      child: Container(
                        color: Colors.transparent,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            StandardCheckbox(
                              caption: S.of(context).litecoin_mweb_allow_coins,
                              captionColor: Colors.white,
                              borderColor: currentTheme.type == ThemeType.bright
                                  ? Colors.white
                                  : Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
                              iconColor: currentTheme.type == ThemeType.bright
                                  ? Colors.white
                                  : Theme.of(context).primaryColor,
                              value:
                                  widget.sendViewModel.coinTypeToSpendFrom == UnspentCoinType.any,
                              onChanged: (bool? value) {
                                sendViewModel.setAllowMwebCoins(value ?? false);
                              },
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }

  void _setEffects(BuildContext context) {
    if (_effectsInstalled) {
      return;
    }

    if (output.address.isNotEmpty) {
      addressController.text = output.address;
    }
    if (output.cryptoAmount.isNotEmpty) {
      cryptoAmountController.text = output.cryptoAmount;
    }
    fiatAmountController.text = output.fiatAmount;
    noteController.text = output.note;
    extractedAddressController.text = output.extractedAddress;

    cryptoAmountController.addListener(() {
      final amount = cryptoAmountController.text;

      if (output.sendAll && amount != S.current.all) {
        output.sendAll = false;
      }

      if (amount != output.cryptoAmount) {
        output.setCryptoAmount(amount);
      }
    });

    fiatAmountController.addListener(() {
      final amount = fiatAmountController.text;

      if (amount != output.fiatAmount) {
        output.sendAll = false;
        output.setFiatAmount(amount);
      }
    });

    noteController.addListener(() {
      final note = noteController.text;

      if (note != output.note) {
        output.note = note;
      }
    });

    reaction((_) => output.sendAll, (bool all) {
      if (all) {
        cryptoAmountController.text = S.current.all;
        fiatAmountController.text = '';
      }
    });

    reaction((_) => sendViewModel.selectedCryptoCurrency, (Currency currency) async {
      if (output.sendAll) {
        output.setSendAll(await sendViewModel.sendingBalance);
      }

      output.setCryptoAmount(cryptoAmountController.text);
    });

    reaction((_) => output.fiatAmount, (String amount) {
      if (amount != fiatAmountController.text) {
        fiatAmountController.text = amount;
      }
    });

    reaction((_) => output.cryptoAmount, (String amount) {
      if (output.sendAll && amount != S.current.all) {
        output.sendAll = false;
      }

      if (amount != cryptoAmountController.text) {
        cryptoAmountController.text = amount;
      }
    });

    reaction((_) => output.address, (String address) {
      if (address != addressController.text) {
        addressController.text = address;
      }
    });

    addressController.addListener(() {
      final address = addressController.text;

      if (output.address != address) {
        output.resetParsedAddress();
        output.address = address;
      }
    });

    reaction((_) => output.note, (String note) {
      if (note != noteController.text) {
        noteController.text = note;
      }
    });

    addressFocusNode.addListener(() async {
      if (!addressFocusNode.hasFocus && addressController.text.isNotEmpty) {
        await output.fetchParsedAddress(context);
      }
    });

    reaction((_) => output.extractedAddress, (String extractedAddress) {
      extractedAddressController.text = extractedAddress;
    });

    if (initialPaymentRequest != null &&
        sendViewModel.walletCurrencyName == initialPaymentRequest!.scheme.toLowerCase()) {
      addressController.text = initialPaymentRequest!.address;
      cryptoAmountController.text = initialPaymentRequest!.amount;
      noteController.text = initialPaymentRequest!.note;
    }

    _effectsInstalled = true;
  }

  Future<void> pickTransactionPriority(BuildContext context) async {
    final items = priorityForWalletType(sendViewModel.walletType);
    final selectedItem = items.indexOf(sendViewModel.feesViewModel.transactionPriority);
    final customItemIndex = sendViewModel.feesViewModel.getCustomPriorityIndex(items);
    final isBitcoinWallet = sendViewModel.walletType == WalletType.bitcoin;
    final maxCustomFeeRate = sendViewModel.feesViewModel.maxCustomFeeRate?.toDouble();
    double? customFeeRate = isBitcoinWallet ? sendViewModel.feesViewModel.customBitcoinFeeRate.toDouble() : null;

    await showPopUp<void>(
      context: context,
      builder: (BuildContext context) {
        int selectedIdx = selectedItem;
        return StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) {
            return Picker(
              items: items,
              displayItem: (TransactionPriority priority) =>
                  sendViewModel.feesViewModel.displayFeeRate(priority, customFeeRate?.round()),
              selectedAtIndex: selectedIdx,
              customItemIndex: customItemIndex,
              maxValue: maxCustomFeeRate,
              title: S.of(context).please_select,
              headerEnabled: !isBitcoinWallet,
              closeOnItemSelected: !isBitcoinWallet,
              mainAxisAlignment: MainAxisAlignment.center,
              sliderValue: customFeeRate,
              onSliderChanged: (double newValue) => setState(() => customFeeRate = newValue),
              onItemSelected: (TransactionPriority priority) {
                sendViewModel.feesViewModel.setTransactionPriority(priority);
                setState(() => selectedIdx = items.indexOf(priority));
              },
            );
          },
        );
      },
    );
    if (isBitcoinWallet) sendViewModel.feesViewModel.customBitcoinFeeRate = customFeeRate!.round();
  }

  void _presentPicker(BuildContext context) {
    showPopUp<void>(
      context: context,
      builder: (_) => CurrencyPicker(
        key: ValueKey('send_page_currency_picker_dialog_button_key'),
        selectedAtIndex: sendViewModel.currencies.indexOf(sendViewModel.selectedCryptoCurrency),
        items: sendViewModel.currencies,
        hintText: S.of(context).search_currency,
        onItemSelected: (Currency cur) =>
            sendViewModel.selectedCryptoCurrency = (cur as CryptoCurrency),
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}
