package com.nexstreaming.nexplayerengine.neximaclient;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;

import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.MediaController;
import android.widget.VideoView;

import com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer;
import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate;
import com.nexstreaming.nexplayerengine.NexLog;

import java.util.ArrayList;
import java.util.List;

public class NexAdsPlayer {
    private final static String LOG_TAG = "NexVASTAdsPlayer";
    private ViewGroup mContainerView;
    private VideoView mVideoView = null;
    private boolean mUseController = false;
    private MediaController mController;
    // VideoAdPlayer interface implementation for the SDK to send ad play/pause type events.
    private VideoAdPlayer mVideoAdPlayer;

    // save AD Positon(mSec) when AD Paused.
    private int mSavedAdPosition;

    // Current ad video URL to start content playback.
    private String mAdVideoUrl;
    private static final Handler mHandler = new Handler();

    // Flag if the current video is an ad (as opposed to a content).
    private boolean mIsAdDisplayed = false;

    private boolean mNeedtoHide = true;
    private final List<VideoAdPlayer.VideoAdPlayerCallback> mAdCallbacks =
            new ArrayList<VideoAdPlayer.VideoAdPlayerCallback>(1);

    private boolean mContentPlayerReady = false;
    private boolean mShouldStartAds = false;

    private AdsEventListener mAdsEventListener = null;

    private boolean mIsSeamlessMode = false;

    public interface AdsEventListener {
        void onAdsUrlLoaded(String adsUrl);
        void onAdsPlayed();
    }

    @SuppressLint("NewApi")
    public NexAdsPlayer(Context context, ViewGroup container, Boolean isSeamlessMode) {
        mVideoView = new VideoView(context);
        mSavedAdPosition = 0;

        FrameLayout framelayout = new FrameLayout(context);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
        container.addView(framelayout, layoutParams);


        layoutParams.gravity = Gravity.CENTER;
        framelayout.setBackgroundColor(Color.BLACK);
        framelayout.addView(mVideoView, layoutParams);

        if(mUseController) {
            mController = new MediaController(context);
            mVideoView.setMediaController(mController);
        }
        mContainerView = container;

        mVideoView.setVisibility(View.INVISIBLE);
        framelayout.setAlpha(0);

        setVideoAdPlayer();

        if (!mIsSeamlessMode)
            setVideoViewListeners();
    }

    /**
     *
     */
    public void setAdsEventListener(AdsEventListener listener){
        mAdsEventListener = listener;
    }
    /**
     * @brief This method returns an implementation of the SDK's VideoAdPlayer interface.
     * @return VideoAdPlayer.
     */
    public VideoAdPlayer getVideoAdPlayer() {
        return mVideoAdPlayer;
    }

    /**
     * @brief This method returns a boolean flag if an ad is displayed.
     * @return \c TRUE if the current playback is ad.
     */
    public boolean isAdDisplayed() {
        return mIsAdDisplayed;
    }

    /**
     * @brief This method returns the UI element for rendering video ad elements.
     * @return NexVideoView.
     */
    public ViewGroup getVideoViewContainer() {
        return mContainerView;
    }

    /**
     * @brief This method releases NexVASTPlayer to destroy the Application.
     * NexVideoView is released internally.
     */
    public void releaseAdsPlayer() {
        if ( mVideoView != null ) {
            mVideoView = null;
        }
        mHandler.removeCallbacksAndMessages(null);
    }

    public void setAdPodInfo(int index, int total) {
        NexLog.i(LOG_TAG, "setAdPodInfo - index :" + index + " / total : " + total);
        if (index >= total)
            mNeedtoHide = true;
        else
            mNeedtoHide = false;
    }

    public void setContentPlayerState(boolean ready) {
        NexLog.i(LOG_TAG, "VideoAdPlayer setContentPlayerState:" + ready);
        mContentPlayerReady = ready;
        if(mContentPlayerReady && mShouldStartAds) {
            mHandler.post(new Runnable() {
                @SuppressLint("NewApi")
                @Override
                public void run() {
                    ViewGroup parent = ((ViewGroup) mVideoView.getParent());
                    if(parent != null) {
                        parent.removeViewInLayout(mVideoView);
                    }

                    FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                            FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);

                    layoutParams.gravity = Gravity.CENTER;
                    parent.addView(mVideoView, layoutParams);

                    mVideoView.setVisibility(View.VISIBLE);
                    ((View) mVideoView.getParent()).setAlpha(1.0f);
                    mVideoView.setZOrderOnTop(true);
                    mVideoView.setZOrderMediaOverlay(true);
                }
            });
        }
    }

    /**
     * VideoAdPlayer implementation.
     */
    private void setVideoAdPlayer() {
        NexLog.i(LOG_TAG, "VideoAdPlayer Constructor");
        mVideoAdPlayer = new VideoAdPlayer() {
            @Override
            public int getVolume() {
                return 0;
            }

            @Override
            public void loadAd(String url) {
                NexLog.d(LOG_TAG, "VideoAdPlayer : loadAd : url : " + url);
                mAdVideoUrl = url;
                if(mAdsEventListener != null){
                    mAdsEventListener.onAdsUrlLoaded(mAdVideoUrl);
                }
            }

            @Override
            public void playAd() {
                NexLog.d(LOG_TAG, "VideoAdPlayer : playAd");
                mIsAdDisplayed = true;
                if (!mIsSeamlessMode) {
                    mHandler.post(new Runnable() {
                        @SuppressLint("NewApi")
                        @Override
                        public void run() {
                            if (mVideoView != null) {
                                mVideoView.setZOrderOnTop(true);
                                mVideoView.setZOrderMediaOverlay(true);
                                if (mSavedAdPosition == 0) {
                                    mShouldStartAds = false;
                                    mVideoView.setVisibility(View.VISIBLE);
                                    ((View) mVideoView.getParent()).setAlpha(1.0f);
                                    mVideoView.setVideoURI(Uri.parse(mAdVideoUrl));

                                    for (VideoAdPlayerCallback callback : mAdCallbacks)
                                        callback.onPlay();
                                } else {
                                    NexLog.d(LOG_TAG, "VideoAdPlayer : resumeAd" + mSavedAdPosition + "mSec");
                                    mVideoView.seekTo(mSavedAdPosition);
                                    mSavedAdPosition = 0;
                                    for (VideoAdPlayerCallback callback : mAdCallbacks)
                                        callback.onResume();
                                }

                            }
                        }
                    });
                }
                if(mAdsEventListener != null){
                    mAdsEventListener.onAdsPlayed();
                }
            }

            @Override
            public void stopAd() {
                NexLog.d(LOG_TAG, "VideoAdPlayer : stopAd, hide:" + mNeedtoHide);
                mIsAdDisplayed = false;
                if (!mIsSeamlessMode) {
                    mHandler.post(new Runnable() {
                        @SuppressLint("NewApi")
                        @Override
                        public void run() {
                            if (mVideoView != null) {
                                mVideoView.stopPlayback();
                                if (mNeedtoHide) {
                                    mVideoView.setVisibility(View.INVISIBLE);
                                    ((View) mVideoView.getParent()).setAlpha(0);
                                }

                            }
                        }
                    });
                }
            }

            @Override
            public void pauseAd() {
                if (!mIsSeamlessMode) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (mVideoView != null) {
                                mSavedAdPosition = mVideoView.getCurrentPosition();
                                mVideoView.pause();
                                NexLog.d(LOG_TAG, "VideoAdPlayer : pauseAd " + mSavedAdPosition + "mSec");
                                for (VideoAdPlayer.VideoAdPlayerCallback callback : mAdCallbacks) {
                                    callback.onPause();
                                }
                            }

                        }
                    });
                }
            }

            @Override
            public void resumeAd() {
                if (!mIsSeamlessMode) {
                    mHandler.post(new Runnable() {
                        @SuppressLint("NewApi")
                        @Override
                        public void run() {
                            if (mVideoView != null) {
                                mVideoView.resume();
                                NexLog.d(LOG_TAG, "VideoAdPlayer : resumeAd" + mSavedAdPosition + "mSec");
                                for (VideoAdPlayer.VideoAdPlayerCallback callback : mAdCallbacks) {
                                    callback.onResume();
                                }
                            }
                        }
                    });
                }
            }

            @Override
            public void addCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
                NexLog.d(LOG_TAG, "VideoAdPlayer : addCallback");
                mAdCallbacks.add(videoAdPlayerCallback);
            }

            @Override
            public void removeCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
                NexLog.d(LOG_TAG, "VideoAdPlayer : removeCallback");
                mAdCallbacks.remove(videoAdPlayerCallback);
            }

            @Override
            public VideoProgressUpdate getAdProgress() {
                if (!mIsSeamlessMode) {
                    if (mVideoView != null) {
                        if (!mIsAdDisplayed || mVideoView.getDuration() <= 0) {
                            return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
                        }
                        return new VideoProgressUpdate(mVideoView.getCurrentPosition(),
                                mVideoView.getDuration());
                    } else {
                        return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
                    }
                }
                return null;
            }
        };
    }

    /**
     * Set NexVideoView listeners.
     */
    private void setVideoViewListeners() {
        mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer var1) {
                NexLog.d(LOG_TAG, "onPrepared");
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if(mIsAdDisplayed) {
                            mVideoView.start();
                        }
                    }
                });
            }
        });
        mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(final MediaPlayer mp) {
                NexLog.d(LOG_TAG, "onContentComplete");
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mVideoView.stopPlayback();
                        if (mIsAdDisplayed) {
                            for (VideoAdPlayer.VideoAdPlayerCallback callback : mAdCallbacks) {
                                callback.onEnded();
                            }
                        }
                        mIsAdDisplayed = false;
                    }
                });
            }
        });

        mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer var1, int var2, int var3) {
                NexLog.v(LOG_TAG, "onError");

                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mVideoView.stopPlayback();
                        if (mIsAdDisplayed) {
                            for (VideoAdPlayer.VideoAdPlayerCallback callback : mAdCallbacks) {
                                callback.onError();
                            }
                            mIsAdDisplayed = false;
                        }
                    }
                });
                return true;
            }
        });
    }
}
