package org.mercury_im.messenger.android.ui.account.detail;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.card.MaterialCardView;

import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.ui.account.login.IkeyBackupCreationFragment;
import org.mercury_im.messenger.android.ui.account.login.IkeySetupFragment;
import org.mercury_im.messenger.android.ui.openpgp.ToggleableFingerprintsAdapter;
import org.mercury_im.messenger.android.ui.openpgp.OpenPgpV4FingerprintFormatter;
import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.pgpainless.key.OpenPgpV4Fingerprint;

import java.util.List;
import java.util.UUID;

import butterknife.BindView;
import butterknife.ButterKnife;
import de.hdodenhof.circleimageview.CircleImageView;

public class AccountDetailsFragment extends Fragment {

    @BindView(R.id.avatar)
    CircleImageView avatar;

    @BindView(R.id.jid)
    TextView jid;

    @BindView(R.id.btn_backup)
    Button localKeyCreateBackupButton;

    @BindView(R.id.btn_share)
    Button localFingerprintShareButton;

    @BindView(R.id.btn_share_ikey)
    Button ikeyFingerprintShareButton;

    @BindView(R.id.btn_backup_ikey)
    Button ikeyCreateBackupButton;

    @BindView(R.id.btn_send_ikey_element)
    Button ikeySendDecisions;

    @BindView(R.id.ikey_fingerprint)
    TextView ikeyFingerprint;

    @BindView(R.id.local_fingerprint)
    TextView localFingerprint;

    @BindView(R.id.fingerprint_list)
    RecyclerView externalFingerprintRecyclerView;

    @BindView(R.id.other_fingerprints_card)
    MaterialCardView otherFingerprintsLayout;

    @BindView(R.id.layout_ikey)
    MaterialCardView ikeyLayout;

    private final UUID accountId;
    private ToggleableFingerprintsAdapter otherFingerprintsAdapter;

    private AndroidAccountDetailsViewModel viewModel;

    public AccountDetailsFragment(UUID accountId) {
        this.accountId = accountId;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_account_details, container, false);
        ButterKnife.bind(this, view);
        setHasOptionsMenu(true);

        externalFingerprintRecyclerView.setAdapter(otherFingerprintsAdapter);
        observeViewModel();

        return view;
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        AndroidAccountDetailsViewModel.AndroidAccountDetailsViewModelFactory factory =
                new AndroidAccountDetailsViewModel.AndroidAccountDetailsViewModelFactory(MercuryImApplication.getApplication(), accountId);
        viewModel = new ViewModelProvider(this, factory)
                .get(AndroidAccountDetailsViewModel.class);

        this.otherFingerprintsAdapter = new ToggleableFingerprintsAdapter(context, this::markFingerprintTrusted);
        this.otherFingerprintsAdapter.setItemLongClickListener(fingerprint -> viewModel.unpublishPublicKey(fingerprint));
    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        inflater.inflate(R.menu.menu_account_details, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {

            case R.id.action_generate_ikey:
                viewModel.onGenerateIkey();
                return true;

            case R.id.action_delete_ikey:
                viewModel.onDeleteIkey();
                return true;

            case R.id.action_restore_ikey_backup:
                viewModel.onRestoreIkeyBackup();
                return true;

            case R.id.action_setup_ikey:
                getParentFragmentManager().beginTransaction()
                        .replace(R.id.fragment, IkeySetupFragment.newInstance(accountId))
                        .commit();
                return true;

            case R.id.action_publish_ikey_element:
                sendIkeyElement();
                return true;

            case R.id.action_send_presence:
                sendPresence();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void markFingerprintTrusted(OpenPgpV4Fingerprint fingerprint, boolean trusted) {
        viewModel.markFingerprintTrusted(fingerprint, trusted);
    }

    private void sendIkeyElement() {
        viewModel.sendIkeyElement(accountId);
    }

    private void sendPresence() {
        viewModel.sendPresence(accountId);
    }

    private void observeViewModel() {
        viewModel.getIkeyFingerprint().observe(getViewLifecycleOwner(), this::displayIkeyFingerprintAndDecisionButton);
        viewModel.getLocalFingerprint().observe(getViewLifecycleOwner(), this::displayLocalOxFingerprint);
        viewModel.getRemoteFingerprints().observe(getViewLifecycleOwner(), this::displayOtherOxFingerprints);

        viewModel.getJid().observe(getViewLifecycleOwner(), accountJid -> jid.setText(accountJid.toString()));

        localFingerprintShareButton.setOnClickListener(v -> {
            OpenPgpV4Fingerprint fingerprint = viewModel.getLocalFingerprint().getValue();
            startShareFingerprintIntent(fingerprint);
        });

        ikeyFingerprintShareButton.setOnClickListener(v -> {
            Optional<OpenPgpV4Fingerprint> fingerprint = viewModel.getIkeyFingerprint().getValue();
            if (fingerprint == null || !fingerprint.isPresent()) {
                return;
            }
            startShareFingerprintIntent(fingerprint.getItem());
        });

        ikeyCreateBackupButton.setOnClickListener(v -> {
            getParentFragmentManager().beginTransaction()
                    .replace(R.id.fragment, IkeyBackupCreationFragment.newInstance(accountId)).commit();
        });

        localKeyCreateBackupButton.setOnClickListener(v -> {
            Toast.makeText(getContext(), "Not yet implemented.", Toast.LENGTH_SHORT).show();
        });

        viewModel.isAccountAuthenticated().observe(this, authenticated -> {
            ikeyCreateBackupButton.setEnabled(authenticated);
            localKeyCreateBackupButton.setEnabled(authenticated);
        });

        ikeySendDecisions.setOnClickListener(v -> sendIkeyElement());
    }

    private void startShareFingerprintIntent(OpenPgpV4Fingerprint fingerprint) {
        Intent sendIntent = new Intent();
        sendIntent.setAction(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_TEXT, "openpgp4fpr:" + fingerprint);
        sendIntent.setType("text/plain");

        Intent shareIntent = Intent.createChooser(sendIntent, "Share OpenPGP Fingerprint");
        startActivity(shareIntent);
    }

    private void displayIkeyFingerprint(Optional<OpenPgpV4Fingerprint> fingerprint) {
        if (fingerprint.isPresent()) {
            ikeyLayout.setVisibility(View.VISIBLE);
            ikeyFingerprint.setText(OpenPgpV4FingerprintFormatter.formatOpenPgpV4Fingerprint(fingerprint.getItem()));
        } else {
            ikeyLayout.setVisibility(View.GONE);
            ikeyFingerprint.setText(null);
        }
    }

    private void displayLocalOxFingerprint(OpenPgpV4Fingerprint fingerprint) {
        if (fingerprint != null) {
            localFingerprint.setText(OpenPgpV4FingerprintFormatter.formatOpenPgpV4Fingerprint(fingerprint));
        } else {
            localFingerprint.setText(null);
        }
    }

    private void displayOtherOxFingerprints(List<FingerprintViewItem> fingerprints) {
        otherFingerprintsAdapter.setItems(fingerprints);
        if (fingerprints.isEmpty()) {
            otherFingerprintsLayout.setVisibility(View.GONE);
        } else {
            otherFingerprintsLayout.setVisibility(View.VISIBLE);
        }
    }

    private void displayIkeyFingerprintAndDecisionButton(Optional<OpenPgpV4Fingerprint> fingerprint) {
        displayIkeyFingerprint(fingerprint);
        displayIkeyDecisionPublishButton(fingerprint);
    }

    private void displayIkeyDecisionPublishButton(Optional<OpenPgpV4Fingerprint> fingerprint) {
        if (fingerprint.isPresent()) {
            ikeySendDecisions.setVisibility(View.VISIBLE);
        } else {
            ikeySendDecisions.setVisibility(View.GONE);
        }
    }

}
