content: /*
   * Copyright (C) 2015 AChep@xda <artemchep@gmail.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   * MA  02110-1301, USA.
   */
  package com.achep.acdisplay.services.media;
  
  import androidx.annotation.NonNull;
  import androidx.annotation.Nullable;
  import android.text.TextUtils;
  
  import com.achep.base.async.TaskQueueThread;
  
  import java.lang.ref.Reference;
  import java.lang.ref.WeakReference;
  
  /**
   * @author Artem Chepurnoy
   */
  public class MediaControllerAsyncWrapper extends MediaController2 {
  
      private final Object monitor = new Object();
      private final MediaController2 mMediaController;
      private T mThread;
  
      public MediaControllerAsyncWrapper(@NonNull MediaController2 mc) {
          super(mc.mContext);
          mMediaController = mc;
      }
  
      @Override
      public void registerListener(@NonNull MediaListener listener) {
          mMediaController.registerListener(listener);
      }
  
      @Override
      public void unregisterListener(@NonNull MediaListener listener) {
          mMediaController.unregisterListener(listener);
      }
  
      @Override
      public void onStart(Object... objects) {
          mMediaController.onStart(objects);
          synchronized (monitor) {
              // Init a new thread.
              mThread = new T(mMediaController);
  //            mThread.start();
          }
      }
  
      @Override
      public void onStop(Object... objects) {
          synchronized (monitor) {
              // Force stop the thread.
  //            mThread.finish(true);
          }
          mMediaController.onStop(objects);
      }
  
      //-- THREADING ------------------------------------------------------------
  
      private static class T extends TaskQueueThread<E> {
          private final Reference<MediaController2> mMediaControllerRef;
  
          public T(@NonNull MediaController2 mc) {
              mMediaControllerRef = new WeakReference<>(mc);
          }
  
          @Override
          protected void onHandleTask(E object) {
              MediaController2 mc = mMediaControllerRef.get();
              if (mc == null) {
                  mRunning = false;
                  return;
              }
  
              if (TextUtils.equals(object.id, mc.getMetadata().id)) {
                  object.run(mc);
              }
          }
  
          @Override
          public void sendTask(@NonNull E object) {
              onHandleTask(object);
          }
  
          @Override
          protected boolean isLost() {
              return false;
          }
      }
  
      /**
       * Represents one single event.
       */
      private static abstract class E {
          @Nullable
          public final String id;
  
          public E(@Nullable String id) {
              this.id = id;
          }
  
          public abstract void run(@NonNull MediaController2 mc);
      }
  
      /**
       * An event to seek to song's specific position.
       *
       * @author Artem Chepurnoy
       */
      private static class EventSeekTo extends E {
          public final long position;
  
          public EventSeekTo(@Nullable String id, long position) {
              super(id);
              this.position = position;
          }
  
          @Override
          public void run(@NonNull MediaController2 mc) {
              mc.seekTo(position);
          }
      }
  
      /**
       * An event to send a media action.
       *
       * @author Artem Chepurnoy
       */
      private static class EventMediaAction extends E {
          public final int action;
  
          public EventMediaAction(@Nullable String id, int action) {
              super(id);
              this.action = action;
          }
  
          @Override
          public void run(@NonNull MediaController2 mc) {
              mc.sendMediaAction(action);
          }
      }
  
  
      //-- BASIC METHODS --------------------------------------------------------
  
      /**
       * {@inheritDoc}
       */
      @Override
      public void sendMediaAction(int action) {
          synchronized (monitor) {
              mThread.sendTask(new EventMediaAction(
                      mMediaController.getMetadata().id,
                      action));
          }
      }
  
      /**
       * {@inheritDoc}
       */
      @Override
      public void seekTo(long position) {
          synchronized (monitor) {
              mThread.sendTask(new EventSeekTo(
                      mMediaController.getMetadata().id,
                      position));
          }
      }
  
      /**
       * {@inheritDoc}
       */
      @Override
      public long getPlaybackBufferedPosition() {
          return mMediaController.getPlaybackBufferedPosition();
      }
  
      /**
       * {@inheritDoc}
       */
      @Override
      public long getPlaybackPosition() {
          return mMediaController.getPlaybackPosition();
      }
  
      /**
       * {@inheritDoc}
       */
      @NonNull
      @Override
      public Metadata getMetadata() {
          return mMediaController.getMetadata();
      }
  
      /**
       * {@inheritDoc}
       */
      @Override
      public int getPlaybackState() {
          return mMediaController.getPlaybackState();
      }
  
  }
  