package org.thoughtcrime.securesms.mediasend;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.Group;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import org.thoughtcrime.securesms.InviteActivity;
import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.ThemeUtil;

import java.util.List;

/**
 * Fragment that selects Signal contacts. Intended to be used in the camera-first capture flow.
 */
public class CameraContactSelectionFragment extends LoggingFragment implements CameraContactAdapter.CameraContactListener {

  private Controller                      controller;
  private CameraContactSelectionViewModel contactViewModel;
  private RecyclerView                    contactList;
  private CameraContactAdapter            contactAdapter;
  private RecyclerView                    selectionList;
  private CameraContactSelectionAdapter   selectionAdapter;
  private Toolbar                         toolbar;
  private View                            sendButton;
  private Group                           selectionFooterGroup;
  private ViewGroup                       cameraContactsEmpty;
  private View                            inviteButton;

  public static Fragment newInstance() {
    return new CameraContactSelectionFragment();
  }


  @Override
  public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);

    this.contactViewModel   = ViewModelProviders.of(requireActivity(), new CameraContactSelectionViewModel.Factory(new CameraContactsRepository(requireContext())))
                                                .get(CameraContactSelectionViewModel.class);
  }

  @Override
  public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    if (!(getActivity() instanceof Controller)) {
      throw new IllegalStateException("Parent activity must implement controller interface.");
    }
    controller = (Controller) getActivity();
  }

  @Override
  public @Nullable View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    int            theme          = DynamicTheme.isDarkTheme(inflater.getContext()) ? R.style.TextSecure_DarkTheme
                                                                                    : R.style.TextSecure_LightTheme;
    return ThemeUtil.getThemedInflater(inflater.getContext(), inflater, theme)
                    .inflate(R.layout.camera_contact_selection_fragment, container, false);
  }

  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    this.contactList          = view.findViewById(R.id.camera_contacts_list);
    this.selectionList        = view.findViewById(R.id.camera_contacts_selected_list);
    this.toolbar              = view.findViewById(R.id.camera_contacts_toolbar);
    this.sendButton           = view.findViewById(R.id.camera_contacts_send_button);
    this.selectionFooterGroup = view.findViewById(R.id.camera_contacts_footer_group);
    this.cameraContactsEmpty  = view.findViewById(R.id.camera_contacts_empty);
    this.inviteButton         = view.findViewById(R.id.camera_contacts_invite_button);
    this.contactAdapter       = new CameraContactAdapter(GlideApp.with(this), this);
    this.selectionAdapter     = new CameraContactSelectionAdapter();

    contactList.setLayoutManager(new LinearLayoutManager(requireContext()));
    contactList.setAdapter(contactAdapter);

    selectionList.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
    selectionList.setAdapter(selectionAdapter);

    ((AppCompatActivity) requireActivity()).setSupportActionBar(toolbar);
    ((AppCompatActivity) requireActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    toolbar.setNavigationOnClickListener(v -> requireActivity().onBackPressed());

    inviteButton.setOnClickListener(v -> onInviteContactsClicked());

    initViewModel();
  }

  @Override
  public void onPrepareOptionsMenu(@NonNull Menu menu) {
    requireActivity().getMenuInflater().inflate(R.menu.camera_contacts, menu);

    MenuItem   searchViewItem                    = menu.findItem(R.id.menu_search);
    SearchView searchView                        = (SearchView) searchViewItem.getActionView();
    SearchView.OnQueryTextListener queryListener = new SearchView.OnQueryTextListener() {
      @Override
      public boolean onQueryTextSubmit(String query) {
        contactViewModel.onQueryUpdated(query);
        return true;
      }

      @Override
      public boolean onQueryTextChange(String query) {
        contactViewModel.onQueryUpdated(query);
        return true;
      }
    };

    searchViewItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
      @Override
      public boolean onMenuItemActionExpand(MenuItem item) {
        searchView.setOnQueryTextListener(queryListener);
        return true;
      }

      @Override
      public boolean onMenuItemActionCollapse(MenuItem item) {
        searchView.setOnQueryTextListener(null);
        contactViewModel.onSearchClosed();
        return true;
      }
    });
  }

  @Override
  public void onContactClicked(@NonNull Recipient recipient) {
    contactViewModel.onContactClicked(recipient);
  }

  @Override
  public void onInviteContactsClicked() {
    startActivity(new Intent(requireContext(), InviteActivity.class));
  }

  private void initViewModel() {
    contactViewModel.getContacts().observe(getViewLifecycleOwner(), contactState -> {
      if (contactState == null) return;

      if (contactState.getContacts().isEmpty() && TextUtils.isEmpty(contactState.getQuery())) {
        cameraContactsEmpty.setVisibility(View.VISIBLE);
        contactList.setVisibility(View.GONE);
        selectionFooterGroup.setVisibility(View.GONE);
      } else {
        cameraContactsEmpty.setVisibility(View.GONE);
        contactList.setVisibility(View.VISIBLE);

        sendButton.setOnClickListener(v -> controller.onCameraContactsSendClicked(contactState.getSelected()));

        contactAdapter.setContacts(contactState.getContacts(), contactState.getSelected());
        selectionAdapter.setRecipients(contactState.getSelected());

        selectionFooterGroup.setVisibility(contactState.getSelected().isEmpty() ? View.GONE : View.VISIBLE);
      }
    });

    contactViewModel.getError().observe(getViewLifecycleOwner(), error -> {
      if (error == null) return;

      if (error == CameraContactSelectionViewModel.Error.MAX_SELECTION) {
        String message = getString(R.string.CameraContacts_you_can_share_with_a_maximum_of_n_conversations, CameraContactSelectionViewModel.MAX_SELECTION_COUNT);
        Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show();
      }
    });
  }

  public interface Controller {
    void onCameraContactsSendClicked(@NonNull List<Recipient> recipients);
  }
}
