package org.thoughtcrime.securesms;

import android.content.ComponentName;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.media3.session.MediaController;
import androidx.media3.session.SessionCommand;
import androidx.media3.session.SessionToken;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEvent;
import com.b44t.messenger.DcMsg;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.ArrayList;
import org.thoughtcrime.securesms.components.audioplay.AudioPlaybackViewModel;
import org.thoughtcrime.securesms.components.audioplay.ChatAudioQueueProvider;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.service.AudioPlaybackService;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.ViewUtil;

public class AllMediaActivity extends PassphraseRequiredActionBarActivity
    implements DcEventCenter.DcEventDelegate {
  private static final String TAG = "AllMediaActivity";

  public static final String CHAT_ID_EXTRA = "chat_id";
  public static final String CONTACT_ID_EXTRA = "contact_id";
  public static final String FORCE_GALLERY = "force_gallery";

  static class TabData {
    final int title;
    final int type1;
    final int type2;
    final int type3;

    TabData(int title, int type1, int type2, int type3) {
      this.title = title;
      this.type1 = type1;
      this.type2 = type2;
      this.type3 = type3;
    }
  }

  private DcContext dcContext;
  private int chatId;
  private int contactId;

  private final ArrayList<TabData> tabs = new ArrayList<>();
  private Toolbar toolbar;
  private TabLayout tabLayout;
  private ViewPager2 viewPager;

  private @Nullable MediaController mediaController;
  private ListenableFuture<MediaController> mediaControllerFuture;
  private AudioPlaybackViewModel playbackViewModel;

  @Override
  protected void onPreCreate() {
    dynamicTheme = new DynamicNoActionBarTheme();
    super.onPreCreate();
    dcContext = DcHelper.getContext(this);
  }

  @Override
  protected void onCreate(Bundle bundle, boolean ready) {
    tabs.add(new TabData(R.string.webxdc_apps, DcMsg.DC_MSG_WEBXDC, 0, 0));
    tabs.add(
        new TabData(
            R.string.tab_gallery, DcMsg.DC_MSG_IMAGE, DcMsg.DC_MSG_GIF, DcMsg.DC_MSG_VIDEO));
    tabs.add(new TabData(R.string.audio, DcMsg.DC_MSG_AUDIO, DcMsg.DC_MSG_VOICE, 0));
    tabs.add(new TabData(R.string.files, DcMsg.DC_MSG_FILE, 0, 0));

    setContentView(R.layout.all_media_activity);

    initializeResources();

    setSupportActionBar(this.toolbar);
    ActionBar supportActionBar = getSupportActionBar();
    if (supportActionBar != null) {
      supportActionBar.setDisplayHomeAsUpEnabled(true);
      supportActionBar.setTitle(
          isGlobalGallery() ? R.string.menu_all_media : R.string.apps_and_media);
    }

    AllMediaPagerAdapter adapter = new AllMediaPagerAdapter(this);
    this.viewPager.setAdapter(adapter);
    this.viewPager.registerOnPageChangeCallback(
        new ViewPager2.OnPageChangeCallback() {
          @Override
          public void onPageSelected(int position) {
            adapter.onPageChanged(position);
          }
        });
    new TabLayoutMediator(
            this.tabLayout,
            this.viewPager,
            (tab, position) -> tab.setText(getString(tabs.get(position).title)))
        .attach();
    if (getIntent().getBooleanExtra(FORCE_GALLERY, false)) {
      this.viewPager.setCurrentItem(1, false);
    }

    DcEventCenter eventCenter = DcHelper.getEventCenter(this);
    eventCenter.addObserver(DcContext.DC_EVENT_CHAT_MODIFIED, this);
    eventCenter.addObserver(DcContext.DC_EVENT_CONTACTS_CHANGED, this);

    int accountId = DcHelper.getAccounts(this).getSelectedAccount().getAccountId();
    playbackViewModel = new ViewModelProvider(this).get(AudioPlaybackViewModel.class);
    playbackViewModel.setQueueProvider(new ChatAudioQueueProvider(this, chatId, accountId));
    initializeMediaController();
  }

  @Override
  public void onDestroy() {
    DcHelper.getEventCenter(this).removeObservers(this);
    if (mediaController != null) {
      MediaController.releaseFuture(mediaControllerFuture);
      mediaController = null;
      playbackViewModel.setMediaController(null);
    }
    playbackViewModel.setQueueProvider(null);
    super.onDestroy();
  }

  @Override
  public void handleEvent(@NonNull DcEvent event) {}

  private void initializeResources() {
    chatId = getIntent().getIntExtra(CHAT_ID_EXTRA, 0);
    contactId = getIntent().getIntExtra(CONTACT_ID_EXTRA, 0);

    if (contactId != 0) {
      chatId = dcContext.getChatIdByContactId(contactId);
    }

    if (chatId != 0) {
      DcChat dcChat = dcContext.getChat(chatId);
      if (!dcChat.isMultiUser()) {
        final int[] members = dcContext.getChatContacts(chatId);
        contactId = members.length >= 1 ? members[0] : 0;
      }
    }

    this.viewPager = ViewUtil.findById(this, R.id.pager);
    this.toolbar = ViewUtil.findById(this, R.id.toolbar);
    this.tabLayout = ViewUtil.findById(this, R.id.tab_layout);
  }

  private void initializeMediaController() {
    SessionToken sessionToken =
        new SessionToken(this, new ComponentName(this, AudioPlaybackService.class));
    mediaControllerFuture = new MediaController.Builder(this, sessionToken).buildAsync();
    mediaControllerFuture.addListener(
        () -> {
          try {
            mediaController = mediaControllerFuture.get();
            addActivityContext(this.getIntent().getExtras(), this.getClass().getName());
            playbackViewModel.setMediaController(mediaController);
          } catch (Exception e) {
            Log.e(TAG, "Error connecting to audio playback service", e);
          }
        },
        ContextCompat.getMainExecutor(this));
  }

  private void addActivityContext(Bundle extras, String activityClassName) {
    if (mediaController == null) return;

    Bundle commandArgs = new Bundle();
    commandArgs.putString("activity_class", activityClassName);
    if (extras != null) {
      commandArgs.putAll(extras);
    }

    SessionCommand updateContextCommand =
        new SessionCommand("UPDATE_ACTIVITY_CONTEXT", Bundle.EMPTY);

    mediaController.sendCustomCommand(updateContextCommand, commandArgs);
  }

  private boolean isGlobalGallery() {
    return contactId == 0 && chatId == 0;
  }

  private class AllMediaPagerAdapter extends FragmentStateAdapter {
    private int currentPosition = -1;

    AllMediaPagerAdapter(FragmentActivity activity) {
      super(activity);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
      TabData data = tabs.get(position);
      Fragment fragment;
      Bundle args = new Bundle();

      if (data.type1 == DcMsg.DC_MSG_IMAGE) {
        fragment = new AllMediaGalleryFragment();
        args.putInt(
            AllMediaGalleryFragment.CHAT_ID_EXTRA,
            (chatId == 0 && !isGlobalGallery()) ? -1 : chatId);
      } else {
        fragment = new AllMediaDocumentsFragment();
        args.putInt(
            AllMediaDocumentsFragment.CHAT_ID_EXTRA,
            (chatId == 0 && !isGlobalGallery()) ? -1 : chatId);
        args.putInt(AllMediaDocumentsFragment.VIEWTYPE1, data.type1);
        args.putInt(AllMediaDocumentsFragment.VIEWTYPE2, data.type2);
      }
      fragment.setArguments(args);
      return fragment;
    }

    @Override
    public int getItemCount() {
      return tabs.size();
    }

    private void onPageChanged(int newPosition) {
      if (currentPosition != -1 && currentPosition != newPosition) {
        for (Fragment fragment : getSupportFragmentManager().getFragments()) {
          if (!(fragment instanceof MessageSelectorFragment)) {
            continue;
          }

          ActionMode action = ((MessageSelectorFragment) fragment).getActionMode();
          if (action != null) {
            action.finish();
          }
        }
      }
      currentPosition = newPosition;
    }
  }

  @Override
  public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    super.onOptionsItemSelected(item);

    int itemId = item.getItemId();
    if (itemId == android.R.id.home) {
      finish();
      return true;
    }

    return false;
  }
}
