package com.castlabs.sdk.broadpeak_demo;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;

import androidx.annotation.Nullable;

import com.castlabs.analytics.AnalyticsMetaData;
import com.castlabs.android.player.PlayerConfig;
import com.castlabs.android.player.models.SideloadedTrack;
import com.castlabs.android.player.models.ThumbnailDataTrack;
import com.castlabs.logutils.Log;
import com.castlabs.sdk.broadpeak.BroadpeakPlugin;
import com.castlabs.sdk.broadpeak.BroadpeakSdkElementExtension;
import com.castlabs.sdk.thumbs.StandaloneThumbnailFactory;
import com.castlabs.sdk.thumbs.StandaloneThumbnailProvider;
import com.castlabs.sdk.thumbs.ThumbsPlugin;
import com.castlabs.sdk.thumbs.ThumbnailProvider;

import java.util.Locale;
import java.util.concurrent.TimeUnit;

import tv.broadpeak.smartlib.session.streaming.StreamingSessionOptions;

/**
 * Demo activity that shows how to use StandaloneThumbnailProvider
 * with a slider to display thumbnails at different time positions
 */
public class ThumbnailSliderDemo extends Activity {

	private static final String TAG = "ThumbnailSliderDemo";
	
	// Bundle keys for the parameters
	public static final String BUNDLE_STREAM_URL = "BUNDLE_STREAM_URL";
	public static final String BUNDLE_CONTENT_DURATION_MS = "BUNDLE_CONTENT_DURATION_MS";
	public static final String BUNDLE_IS_LIVE = "BUNDLE_IS_LIVE";
	public static final String BUNDLE_ASSET_ID = "BUNDLE_ASSET_ID";
	
	// Parameters that can be set via bundle
	private String streamUrl;
	private long contentDurationMs;
	private boolean isLive = false;
	private String assetId = "default_asset_id";

	private ImageView thumbnailImageView;
	private SeekBar positionSlider;
	private TextView timePositionText;
	
	private StandaloneThumbnailProvider thumbnailProvider;
	private final Handler mainHandler = new Handler(Looper.getMainLooper());
	
	@Override
	protected void onCreate(@Nullable Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_thumbnail_slider_demo);
		
		// Get parameters from bundle or use defaults
		Bundle bundle = getIntent().getExtras();
		if (bundle != null) {
			streamUrl = bundle.getString(BUNDLE_STREAM_URL, null);
			contentDurationMs = bundle.getLong(BUNDLE_CONTENT_DURATION_MS, -1L);
			isLive = bundle.getBoolean(BUNDLE_IS_LIVE, false);
			assetId = bundle.getString(BUNDLE_ASSET_ID, "default_asset_id");
		}

		if (streamUrl == null) {
			timePositionText.setText("Error: Stream URL is required");
			return;
		}
		
		// Initialize views
		thumbnailImageView = findViewById(R.id.thumbnailImageView);
		positionSlider = findViewById(R.id.positionSlider);
		timePositionText = findViewById(R.id.timePositionText);
		
		// Set up slider
		positionSlider.setMax(100); // Use percentage (0-100)
		
		// Initialize the thumbnail provider
		initializeThumbnailProvider();
		
		// Set up slider listener
		positionSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
				// Update the time position text as user moves the slider
				long positionMs = calculatePositionFromProgress(progress);
				updateTimePositionText(positionMs);
			}
			
			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
				// No action needed
			}
			
			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				// When user stops moving the slider, request the thumbnail
				requestThumbnail(calculatePositionFromProgress(seekBar.getProgress()));
			}
		});
	}
	
	/**
	 * Initialize the thumbnail provider
	 */
	private void initializeThumbnailProvider() {
		PlayerConfig config = new PlayerConfig.Builder(streamUrl).get();

		// Create the standalone thumbnail provider
		thumbnailProvider = StandaloneThumbnailFactory.getProvider(config);
		
		if (thumbnailProvider != null) {
			// Create Analytics Metadata for Broadpeak with custom parameters and options
			Bundle customParameters = new Bundle();
			customParameters.putString("myCustomParam", "myCustomValue");

			SparseArray<Object> options = new SparseArray<>();
			options.put(StreamingSessionOptions.GDPR_PREFERENCE, StreamingSessionOptions.GDPR_CLEAR);

			AnalyticsMetaData broadpeakMetadata = new BroadpeakPlugin.MetadataBuilder(isLive, assetId)
					.customParameters(customParameters)
					.options(options)
					// Optional: Disable precache
					//.precache(false)
					.get();
			
			// Add the Broadpeak extension with metadata
			thumbnailProvider.addExtension(new BroadpeakSdkElementExtension(broadpeakMetadata));
			
			// Prepare the provider to speed up upcoming thumbnail requests
			thumbnailProvider.prepare();
		} else {
			// Handle error - provider could not be created
			timePositionText.setText("Error: Could not create thumbnail provider");
		}
	}
	
	/**
	 * Request a thumbnail for the given position
	 * 
	 * @param positionMs The position in milliseconds
	 */
	private void requestThumbnail(final long positionMs) {
		if (thumbnailProvider == null) {
			return;
		}
		
		final long positionUs = TimeUnit.MILLISECONDS.toMicros(positionMs);
		
		// Update the position text to show it's loading
		timePositionText.setText(String.format(Locale.US, "Loading thumbnail at %s", formatTime(positionMs)));
		
		// Request the thumbnail
		thumbnailProvider.getThumbnail(positionUs, new ThumbnailProvider.Callback() {
			@Override
			public void onThumbnailLoaded(final long requestedPositionUs, final long actualPositionUs, @Nullable final Bitmap thumbnail) {
				// Make sure we run on the main thread
				mainHandler.post(new Runnable() {
					@Override
					public void run() {
						if (thumbnail != null) {
							// Display the thumbnail
							thumbnailImageView.setVisibility(View.VISIBLE);
							thumbnailImageView.setImageBitmap(thumbnail);

							// Update text to show actual position vs requested
							long requestedMs = TimeUnit.MICROSECONDS.toMillis(requestedPositionUs);
							long actualMs = actualPositionUs != -1 ? TimeUnit.MICROSECONDS.toMillis(actualPositionUs) : -1;

							if (actualMs != -1) {
								timePositionText.setText(String.format(Locale.US,
										"Requested: %s | Actual: %s",
										formatTime(requestedMs),
										formatTime(actualMs)));
							} else {
								timePositionText.setText(String.format(Locale.US,
										"Requested: %s | No thumbnail available",
										formatTime(requestedMs)));
							}
						} else {
							// No thumbnail available
							thumbnailImageView.setVisibility(View.INVISIBLE);
							timePositionText.setText(String.format(Locale.US,
									"No thumbnail available at %s",
									formatTime(TimeUnit.MICROSECONDS.toMillis(requestedPositionUs))));
						}
					}
				});
			}

			@Override
			public void onThumbnailLoadError(long requestedPositionUs, @Nullable Exception exception) {
				Log.e(TAG, "Encountered Error while loading Position = "+requestedPositionUs);
				if(exception != null) {
					Log.e(TAG, exception.toString());
				}
			}
		}, ThumbsPlugin.THUMBNAIL_INDEX_CLOSEST);
	}
	
	/**
	 * Calculate the position in milliseconds from the slider progress (0-100)
	 */
	private long calculatePositionFromProgress(int progress) {
		return (long) (progress / 100.0 * contentDurationMs);
	}
	
	/**
	 * Update the time position text
	 */
	private void updateTimePositionText(long positionMs) {
		timePositionText.setText(formatTime(positionMs));
	}
	
	/**
	 * Format time in a readable format (mm:ss)
	 */
	private String formatTime(long timeMs) {
		long totalSeconds = timeMs / 1000;
		long minutes = totalSeconds / 60;
		long seconds = totalSeconds % 60;
		return String.format(Locale.US, "%d:%02d", minutes, seconds);
	}
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		
		// Clean up resources
		if (thumbnailProvider != null) {
			thumbnailProvider.destroy();
			thumbnailProvider = null;
		}
	}
}
