package com.castlabs.sdk.youbora_demo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

import com.castlabs.android.player.AbstractPlayerListener;
import com.castlabs.android.player.PlayerController;
import com.castlabs.android.player.PlayerListener;
import com.castlabs.sdk.youbora.YouboraAnalyticsSession;
import com.google.android.material.snackbar.Snackbar;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.castlabs.analytics.AnalyticsSession;
import com.castlabs.android.player.PlayerView;
import com.castlabs.android.views.SubtitlesViewComponent;
import com.castlabs.sdk.playerui.PlayerControllerProgressBar;
import com.castlabs.sdk.playerui.PlayerControllerView;
import com.npaw.NpawPlugin;

import androidx.annotation.NonNull;

public class ReleasablePlayerPlaybackDemo extends Activity {

	private AnalyticsSession analyticsSession = null;

	private static final String TAG = "ReleasablePlayerDemo";
	// This is the player view that we use to start playback
	private PlayerView playerView;

	// This is an example implementation that demonstrates how you can
	// listen to changes on the player controller and how you can access the
	// SubtitleViewComponent to apply adjustments.
	//
	// In this example we add some padding to move the subtitles view up a bit when
	// we are showing the controller.
	private final PlayerControllerView.Listener playerControllerViewListener = new PlayerControllerView.Listener() {
		@Override
		public void onVisibilityChanged(int visibility) {
			// This is how you can get a component, in this case the SubtitlesViewComponent
			// from the player view.
			SubtitlesViewComponent svc = playerView.getComponent(SubtitlesViewComponent.class);
			if (svc != null && svc.getView() != null) {
				if (visibility == View.VISIBLE) {
					svc.getView().setPadding(0, 0, 0, playerControllerView.getHeight());
				} else {
					svc.getView().setPadding(0, 0, 0, 0);
				}
			}
		}
	};
	private final PlayerListener playerListener = new AbstractPlayerListener() {
		@Override
		public void onStateChanged(@NonNull PlayerController.State state) {
			updateUiState();
		}
	};
	private PlayerControllerView playerControllerView;
	private Button buttonPlayer;
	private Button buttonPlayPause;
	private boolean playerReleased;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_releasable_playback_demo);

		// Get the view components from the layout
		playerView = (PlayerView) findViewById(R.id.player_view);
		// Get the controller view
		playerControllerView = (PlayerControllerView) findViewById(R.id.player_controls);

		// (Optional) Youbora Sessions tracking
		//NpawPlugin youboraPlugin = ((DemoApp) getApplicationContext()).youboraPlugin;
		//youboraPlugin.getAppAnalytics().begin(TAG);

		// (Optional) Set the Youbora plugin to use before opening the PlayerController
		// This is not needed if the Youbora's Plugin instance is the same as set on
		// the app's onCreate
		//YouboraAnalyticsSession component = playerView.getPlayerController().getComponent(YouboraAnalyticsSession.class);
		//component.setPlugin(youboraPlugin);

		buttonPlayer = findViewById(R.id.buttonPlayer);
		buttonPlayPause = findViewById(R.id.buttonPlayPause);
		buttonPlayPause.setOnClickListener(this::onPlayPauseClick);
		buttonPlayer.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (playerReleased) {
					startPlayback(true);
				} else {
					stopPlayback();
				}
				updateUiState();
			}
		});

		startPlayback(false);
	}

	private void onPlayPauseClick(View view) {
		final PlayerController pc = playerView.getPlayerController();
		final PlayerController.State playerState = pc.getPlayerState();
		if (playerState == PlayerController.State.Playing) {
			pc.pause();
		} else if (playerState == PlayerController.State.Pausing) {
			pc.play();
		}
	}

	private void updateUiState() {
		buttonPlayer.setText(playerReleased? "Open player" : "Release player");
		final PlayerController playerController = playerView.tryPlayerController();
		if (playerController == null) {
			buttonPlayPause.setEnabled(false);
			return;
		}
		final PlayerController.State playerState = playerController.getPlayerState();
		if (playerState == PlayerController.State.Playing) {
			buttonPlayPause.setText("Pause");
			buttonPlayPause.setEnabled(true);
		} else if (playerState == PlayerController.State.Pausing) {
			buttonPlayPause.setText("Play");
			buttonPlayPause.setEnabled(true);
		} else {
			buttonPlayPause.setEnabled(false);
		}
	}

	private void startPlayback(boolean attachListeners) {
		// This demo assumes that you send an intent to this Activity that contains the
		// playback information. We need to pass the intents bundle on to the PlayerController
		// to start playback. The open() method might throw an Exception in case the bundle
		// contains not all mandatory parameters or the parameters are malformed.
		final Intent i = getIntent();
		if (i != null) {

			if (attachListeners) {
				attachListenersAndRestoreAnalytics();
			}
			try {
				playerView.getPlayerController().open(i.getExtras());
			} catch (Exception e) {
				Log.e(TAG, "Error while opening player: " + e.getMessage(), e);
				Snackbar.make(playerView, "Error while opening player: " + e.getMessage(),
						Snackbar.LENGTH_INDEFINITE).show();
			}
			playerReleased = false;
		} else {
			Snackbar.make(playerView, "No intent specified", Snackbar.LENGTH_INDEFINITE).show();
		}
	}

	private void stopPlayback() {
		detachListenersAndSaveAnalytics();
		// Release player
		playerView.getPlayerController().release();
		playerReleased = true;
	}

	// Delegate the onStart event to the player views lifecycle delegate.
	// The delegate will make sure that the screen saver will be disabled and
	// the display will not go to sleep
	@Override
	protected void onStart() {
		super.onStart();
		playerView.getLifecycleDelegate().start(this);
	}

	@Override
	protected void onPause() {
		super.onPause();
		detachListenersAndSaveAnalytics();
	}

	// Delegate the onResume event to the player views lifecycle delegate.
	// The delegate ensures that the player recovers from a saved state. This needs to
	// be implemented to ensure the the user can for example go to the home screen and
	// come back to this activity.
	@Override
	protected void onResume() {
		super.onResume();
		attachListenersAndRestoreAnalytics();
		// Bind the controller view and its listener
		playerControllerView.bind(playerView);
		playerControllerView.addListener(playerControllerViewListener);

		PlayerControllerProgressBar progressBar = (PlayerControllerProgressBar) findViewById(R.id.progress_bar);
		progressBar.bind(playerView.getPlayerController());

		playerView.getLifecycleDelegate().resume();
		updateUiState();
	}

	private void attachListenersAndRestoreAnalytics() {
		final PlayerController playerController = playerView.getPlayerController();
		// Restore old analytics session
		if (analyticsSession != null) {
			playerController.setAnalyticsSession(analyticsSession);
			analyticsSession = null;
		}
		playerController.addPlayerListener(playerListener);
	}

	private void detachListenersAndSaveAnalytics() {
		final PlayerController playerController = playerView.tryPlayerController();
		if (playerController == null) {
			return;
		}
		// Keep analytics session
		analyticsSession = playerController.getAnalyticsSession();
		if (analyticsSession != null) {
			analyticsSession.detachFromController();
		}
		playerController.removePlayerListener(playerListener);
	}

	// Delegate the onStop event to the player views lifecycle delegate.
	// We release the player when the activity is stopped. This will release all the player
	// resources and save the current playback state. Saving the state is required so the
	// onResume callback can recover properly.
	@Override
	protected void onStop() {
		super.onStop();

		// Unbind the player controller view and remove the listener
		playerControllerView.unbind();
		playerControllerView.removeListener(playerControllerViewListener);

		playerView.getLifecycleDelegate().releasePlayer(false);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		// The activity is about to be destroyed and since the analytics session was detached
		// manually we need to stop it manually as well
		if (analyticsSession != null) {
			analyticsSession.stop();
			analyticsSession = null;
		}
	}

}
