package com.castlabs.sdk.broadpeak_demo.ads;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.castlabs.android.adverts.Ad;
import com.castlabs.android.adverts.AdApi;
import com.castlabs.android.adverts.AdInterface;
import com.castlabs.android.player.PlayerController;
import com.castlabs.android.player.exceptions.CastlabsPlayerException;
import com.castlabs.logutils.Log;
import com.castlabs.sdk.broadpeak_demo.R;
import com.castlabs.utils.TimeUtils;

import java.util.Locale;

/**
 * Simple overlay UI to surface SSAI ad information and allow skipping when available.
 */
public class AdUi extends RelativeLayout implements AdInterface.Listener {

	private static final String TAG = "BroadpeakAdUi";

	private Button skipButton;
	private Button learnMoreButton;
	private ProgressBar progressBar;
	private TextView statusText;

	@Nullable
	private PlayerController playerController;
	@Nullable
	private AdApi adApi;
	@Nullable
	private Ad currentAd;

	public AdUi(@NonNull Context context) {
		super(context);
		init();
	}

	public AdUi(@NonNull Context context, @Nullable AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public AdUi(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	}

	private void init() {
		final LayoutInflater inflater = LayoutInflater.from(getContext());
		inflater.inflate(R.layout.custom_ad_ui, this, true);
		skipButton = findViewById(R.id.adSkipButton);
		learnMoreButton = findViewById(R.id.adLearnMoreButton);
		statusText = findViewById(R.id.adTimeProgress);
		progressBar = findViewById(R.id.adProgressBar);
		setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
		setVisibility(GONE);

		skipButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (adApi != null) {
					adApi.skipAd();
				}
			}
		});

		learnMoreButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (currentAd == null || currentAd.clickthroughUrl == null) {
					return;
				}
				if (adApi != null) {
					adApi.clickthrough();
				}
				try {
					final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(currentAd.clickthroughUrl));
					getContext().startActivity(intent);
				} catch (ActivityNotFoundException e) {
					Log.w(TAG, "Unable to open clickthrough URL", e);
				}
			}
		});
	}

	public void bind(@NonNull PlayerController controller) {
		unbind();
		playerController = controller;
		setApi(controller.getAdInterface().getAdApi());
		controller.getAdInterface().addAdListener(this);
	}

	public void unbind() {
		if (playerController != null) {
			playerController.getAdInterface().removeAdListener(this);
			playerController = null;
		}
		setApi(null);
		currentAd = null;
		setVisibility(GONE);
	}

	public void setApi(@Nullable AdApi api) {
		adApi = api;
	}

	@Override
	public void onAdWillStart(@NonNull Ad ad) {
		setVisibility(VISIBLE);
	}

	@Override
	public void onAdStarted(@NonNull Ad ad) {
		currentAd = ad;
		Log.d(TAG, "onAdStarted: " + ad.id + " - " + ad.title);
		setVisibility(VISIBLE);
		updateLearnMoreButton();
		onAdPlaybackPositionChanged(0);
	}

	@Override
	public void onAdCompleted() {
		hide();
	}

	@Override
	public void onAdError(Ad ad, CastlabsPlayerException exception) {
		Log.w(TAG, "Ad error: " + exception.getMessage());
		hide();
	}

	@Override
	public void onAdSkipped() {
		hide();
	}

	@Override
	public void onAdPlaybackPositionChanged(long playbackPositionMs) {
		if (currentAd == null || currentAd.durationMs <= 0) {
			return;
		}
		final long adTimeLeftSec = TimeUtils.ms2s(Math.max(0, currentAd.durationMs - playbackPositionMs));
		final int percentage = (int) Math.min(100, Math.max(0, playbackPositionMs * 100 / currentAd.durationMs));
		progressBar.setProgress(percentage);

		statusText.setText(buildStatusText(adTimeLeftSec));
		updateSkipButton(playbackPositionMs);
		updateLearnMoreButton();
	}

	@Override
	public void onAdPaused() {
		// No-op
	}

	@Override
	public void onAdResumed(Ad ad) {
		// No-op
	}

	@Override
	public void onAdClicked(String clickthroughUrl) {
		// No-op
	}

	private void updateSkipButton(long playbackPositionMs) {
		if (currentAd == null || !currentAd.isSkippable) {
			skipButton.setVisibility(GONE);
			return;
		}
		skipButton.setVisibility(VISIBLE);
		final double elapsedSeconds = playbackPositionMs / 1000.0;
		final double timeToSkip = Math.max(0.0, currentAd.skipTimeOffset - elapsedSeconds);
		if (timeToSkip > 0.0) {
			skipButton.setEnabled(false);
			final int remaining = (int) Math.ceil(timeToSkip);
			skipButton.setText(getResources().getString(R.string.ad_skip_in, remaining));
		} else {
			skipButton.setEnabled(true);
			skipButton.setText(R.string.ad_skip_label);
		}
	}

	private void updateLearnMoreButton() {
		if (currentAd != null && currentAd.clickthroughUrl != null) {
			learnMoreButton.setVisibility(VISIBLE);
		} else {
			learnMoreButton.setVisibility(GONE);
		}
	}

	private void hide() {
		setVisibility(GONE);
		currentAd = null;
		skipButton.setVisibility(GONE);
		skipButton.setEnabled(false);
		skipButton.setText(R.string.ad_skip_label);
		learnMoreButton.setVisibility(GONE);
		statusText.setText("");
		progressBar.setProgress(0);
	}

	@NonNull
	private String buildStatusText(long adTimeLeftSec) {
		if (currentAd == null) {
			return "";
		}
		final StringBuilder sb = new StringBuilder("Ad ");
		int adPosition = currentAd.adPod.adPosition;
		int totalAds = currentAd.adPod.totalAds;
		if (totalAds > 0) {
			if (adPosition <= 0) {
				adPosition = 1;
			}
			sb.append(adPosition);
			if (totalAds > 1) {
				sb.append(" of ").append(totalAds);
			}
		}
		if (currentAd.title != null) {
			sb.append(": ").append(currentAd.title);
		}
		sb.append(" ").append("(").append(String.format(Locale.US, "%d:%02d", adTimeLeftSec / 60, adTimeLeftSec % 60)).append(")");
		return sb.toString();
	}
}
