content: package de.danoeh.antennapod.ui.screen.playback.audio;
  
  import android.app.Activity;
  import android.content.Context;
  import android.content.SharedPreferences;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.MenuItem;
  import android.view.View;
  import android.view.ViewGroup;
  
  import androidx.fragment.app.Fragment;
  
  import de.danoeh.antennapod.R;
  import de.danoeh.antennapod.playback.service.PlaybackController;
  import de.danoeh.antennapod.storage.database.DBReader;
  import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
  import de.danoeh.antennapod.ui.cleaner.ShownotesCleaner;
  import de.danoeh.antennapod.model.feed.FeedMedia;
  import de.danoeh.antennapod.model.playback.Playable;
  import de.danoeh.antennapod.ui.view.ShownotesWebView;
  import io.reactivex.rxjava3.core.Maybe;
  import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
  import io.reactivex.rxjava3.disposables.Disposable;
  import io.reactivex.rxjava3.schedulers.Schedulers;
  
  /**
   * Displays the description of a Playable object in a Webview.
   */
  public class ItemDescriptionFragment extends Fragment {
      private static final String TAG = "ItemDescriptionFragment";
  
      private static final String PREF = "ItemDescriptionFragmentPrefs";
      private static final String PREF_SCROLL_Y = "prefScrollY";
      private static final String PREF_PLAYABLE_ID = "prefPlayableId";
  
      private ShownotesWebView webvDescription;
      private Disposable webViewLoader;
      private PlaybackController controller;
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          Log.d(TAG, "Creating view");
          View root = inflater.inflate(R.layout.item_description_fragment, container, false);
          webvDescription = root.findViewById(R.id.webview);
          webvDescription.setTimecodeSelectedListener(time -> {
              if (controller != null) {
                  controller.seekTo(time);
              }
          });
          webvDescription.setPageFinishedListener(() -> {
              // Restoring the scroll position might not always work
              webvDescription.postDelayed(ItemDescriptionFragment.this::restoreFromPreference, 50);
          });
  
          root.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
              @Override
              public void onLayoutChange(View v, int left, int top, int right,
                      int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                  if (root.getMeasuredHeight() != webvDescription.getMinimumHeight()) {
                      webvDescription.setMinimumHeight(root.getMeasuredHeight());
                  }
                  root.removeOnLayoutChangeListener(this);
              }
          });
          registerForContextMenu(webvDescription);
          return root;
      }
  
      @Override
      public void onDestroy() {
          super.onDestroy();
          Log.d(TAG, "Fragment destroyed");
          if (webvDescription != null) {
              webvDescription.removeAllViews();
              webvDescription.destroy();
          }
      }
  
      @Override
      public boolean onContextItemSelected(MenuItem item) {
          return webvDescription.onContextItemSelected(item);
      }
  
      private void load() {
          Log.d(TAG, "load()");
          if (webViewLoader != null) {
              webViewLoader.dispose();
          }
          Context context = getContext();
          if (context == null) {
              return;
          }
          webViewLoader = Maybe.<String>create(emitter -> {
              Playable media = controller.getMedia();
              if (media == null) {
                  emitter.onComplete();
                  return;
              }
              if (media instanceof FeedMedia) {
                  FeedMedia feedMedia = ((FeedMedia) media);
                  if (feedMedia.getItem() == null) {
                      feedMedia.setItem(DBReader.getFeedItem(feedMedia.getItemId()));
                  }
                  DBReader.loadDescriptionOfFeedItem(feedMedia.getItem());
              }
              ShownotesCleaner shownotesCleaner = new ShownotesCleaner(
                      context, media.getDescription(), media.getDuration());
              emitter.onSuccess(shownotesCleaner.processShownotes());
          })
                  .subscribeOn(Schedulers.io())
                  .observeOn(AndroidSchedulers.mainThread())
                  .subscribe(data -> {
                      webvDescription.loadDataWithBaseURL("https://127.0.0.1", data, "text/html",
                              "utf-8", "about:blank");
                      Log.d(TAG, "Webview loaded");
                  }, error -> Log.e(TAG, Log.getStackTraceString(error)));
      }
  
      @Override
      public void onPause() {
          super.onPause();
          savePreference();
      }
  
      private void savePreference() {
          Log.d(TAG, "Saving preferences");
          SharedPreferences prefs = getActivity().getSharedPreferences(PREF, Activity.MODE_PRIVATE);
          SharedPreferences.Editor editor = prefs.edit();
          if (controller != null && webvDescription != null) {
              Log.d(TAG, "Saving scroll position: " + webvDescription.getScrollY());
              editor.putInt(PREF_SCROLL_Y, webvDescription.getScrollY());
              editor.putString(PREF_PLAYABLE_ID, "" + PlaybackPreferences.getCurrentlyPlayingFeedMediaId());
          } else {
              Log.d(TAG, "savePreferences was called while media or webview was null");
              editor.putInt(PREF_SCROLL_Y, -1);
              editor.putString(PREF_PLAYABLE_ID, "");
          }
          editor.apply();
      }
  
      private void restoreFromPreference() {
          Log.d(TAG, "Restoring from preferences");
          Activity activity = getActivity();
          if (activity != null) {
              SharedPreferences prefs = activity.getSharedPreferences(PREF, Activity.MODE_PRIVATE);
              String id = prefs.getString(PREF_PLAYABLE_ID, "");
              int scrollY = prefs.getInt(PREF_SCROLL_Y, -1);
              if (controller != null && scrollY != -1
                      && id.equals("" + PlaybackPreferences.getCurrentlyPlayingFeedMediaId())
                      && webvDescription != null) {
                  Log.d(TAG, "Restored scroll Position: " + scrollY);
                  webvDescription.scrollTo(webvDescription.getScrollX(), scrollY);
              }
          }
      }
  
      public void scrollToTop() {
          webvDescription.scrollTo(0, 0);
          savePreference();
      }
  
      @Override
      public void onStart() {
          super.onStart();
          controller = new PlaybackController(getActivity()) {
              @Override
              public void loadMediaInfo() {
                  load();
              }
          };
          controller.init();
          load();
      }
  
      @Override
      public void onStop() {
          super.onStop();
  
          if (webViewLoader != null) {
              webViewLoader.dispose();
          }
          controller.release();
          controller = null;
      }
  }
  