package org.mercury_im.messenger.android.ui.roster.contacts.detail;

import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

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

import com.google.android.material.card.MaterialCardView;
import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;

import org.mercury_im.messenger.android.ui.openpgp.ToggleableFingerprintsAdapter;
import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.ui.chat.ChatActivity;
import org.mercury_im.messenger.android.util.ColorUtil;
import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;

import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.Completable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

public class ContactDetailFragment extends Fragment {

    private static final Logger LOGGER = Logger.getLogger(ContactDetailFragment.class.getName());

    @BindView(R.id.contact_avatar)
    ImageView contactAvatar;

    @BindView(R.id.contact_status_badge)
    ImageView contactStatusBadge;

    @BindView(R.id.contact_name)
    TextView contactName;

    @BindView(R.id.contact_address)
    TextView contactAddress;

    @BindView(R.id.contact_presence)
    TextView contactPresence;

    @BindView(R.id.contact_account)
    TextView contactAccount;

    @BindView(R.id.contact_groups)
    ChipGroup contactGroups;

    @BindView(R.id.fab)
    ExtendedFloatingActionButton fab;

    @BindView(R.id.button_add_to_group)
    Button button;

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

    @BindView(R.id.contact_fingerprints)
    MaterialCardView fingerprintsLayout;

    private ContactDetailViewModel viewModel;
    private ToggleableFingerprintsAdapter fingerprintsAdapter;

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

        if (fab != null) {
            fab.setOnClickListener(v -> {
                Intent intent = new Intent(getContext(), ChatActivity.class);
                intent.putExtra(ChatActivity.EXTRA_JID, viewModel.getContactAddress().getValue());
                intent.putExtra(ChatActivity.EXTRA_ACCOUNT, viewModel.getAccountId().getValue().toString());
                startActivity(intent);
            });
        }

        contactName.setOnClickListener(v -> displayChangeContactNameDialog());

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewModel.addContactToRosterGroup().subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe();
            }
        });

        fingerprintsAdapter = new ToggleableFingerprintsAdapter(
                (fingerprint, checked) -> viewModel.markFingerprintTrusted(fingerprint, checked));
        fingerprintRecyclerView.setAdapter(fingerprintsAdapter);

        return view;
    }

    private void displayChangeContactNameDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        builder.setTitle("Edit Contact Name");
        final EditText editText = new EditText(getContext());
        editText.setText(contactName.getText());
        builder.setView(editText)
                .setPositiveButton("Save", (dialog, which) -> {
                    Completable.fromAction(() -> viewModel.changeContactName(editText.getText().toString())).subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(() -> {}, e -> Log.e(Messenger.TAG, "Error changing contact name", e));
                })
                .setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());

        builder.show();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        viewModel = new ViewModelProvider((ViewModelStoreOwner) context).get(ContactDetailViewModel.class);

        observeViewModel();
    }

    private void observeViewModel() {
        viewModel.getContactAvatar().observe(this, drawable -> contactAvatar.setImageDrawable(drawable));
        viewModel.getContactPresenceMode().observe(this, mode -> {
            int color = 0;
            switch (mode) {
                case chat:
                case available:
                    color = ColorUtil.rgb(0, 255, 0);
                    break;
                case away:
                case xa:
                    color = ColorUtil.rgb(255, 128, 0);
                    break;
                case dnd:
                    color = ColorUtil.rgb(255, 0, 0);
                    break;
            }
            contactStatusBadge.setColorFilter(color);
        });
        viewModel.getContactName().observe(this, name -> contactName.setText(name));
        viewModel.getContactAddress().observe(this, address -> contactAddress.setText(address));
        viewModel.getContactPresenceStatus().observe(this, presenceText -> contactPresence.setText(presenceText));
        viewModel.getContactAccountAddress().observe(this, address -> contactAccount.setText(address));
        viewModel.getContactGroups().observe(this, this::setRosterGroups);
        viewModel.getContactFingerprints().observe(this, this::setFingerprints);
    }

    private void setRosterGroups(List<String> groups) {
        contactGroups.removeAllViews();
        for (String group : groups) {
            Chip chip = new Chip(contactGroups.getContext());
            chip.setText(group);
            chip.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    viewModel.removeContactFromRosterGroup(group)
                            .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                            .subscribe();
                    return true;
                }
            });
            contactGroups.addView(chip);
        }
    }

    private void setFingerprints(List<FingerprintViewItem> fingerprints) {
        LOGGER.log(Level.INFO, "Display fingerprints: " + Arrays.asList(fingerprints.toArray()));
        fingerprintsLayout.setVisibility(fingerprints.isEmpty() ? View.GONE : View.VISIBLE);
        fingerprintsAdapter.setItems(fingerprints);
    }
}
