package co.pixelbeard.theanfieldwrap.podcasts;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;

import com.google.firebase.crashlytics.FirebaseCrashlytics;
import com.loopeer.shadow.ShadowView;
import com.makeramen.roundedimageview.RoundedImageView;
import com.taishi.library.Indicator;
import com.tonyodev.fetch2.Download;
import com.tonyodev.fetch2.Status;

import java.util.List;
import java.util.Locale;

import butterknife.BindView;
import butterknife.ButterKnife;
import co.pixelbeard.theanfieldwrap.R;
import co.pixelbeard.theanfieldwrap.data.Podcast;
import co.pixelbeard.theanfieldwrap.databinding.ItemLoadingBinding;
import co.pixelbeard.theanfieldwrap.loading.LoadingViewHolder;
import co.pixelbeard.theanfieldwrap.playerService.MediaConstants;
import co.pixelbeard.theanfieldwrap.playerService.MediaPlayerInterface;
import co.pixelbeard.theanfieldwrap.playerService.PodcastStorageUtil;
import co.pixelbeard.theanfieldwrap.utils.DateUtils;
import co.pixelbeard.theanfieldwrap.utils.FontUtils;
import co.pixelbeard.theanfieldwrap.utils.GlideApp;
import co.pixelbeard.theanfieldwrap.utils.PrefKey;
import co.pixelbeard.theanfieldwrap.utils.PrefUtils;
import co.pixelbeard.theanfieldwrap.utils.SubscriptionUtils;
import rx.Observer;

/**
 * Created by Michael Stoddart
 * 01/01/2019.
 */
public class PodcastsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<Podcast> mPodcasts;
    private Podcast featuredPodcast;
    private OnPodcastSelectedListener mListener;
    private MediaPlayerInterface mediaPlayerInterface;
    private Observer<String> serviceObserver;
    private int mSelectedPodcast = -1;

    private final int VIEW_TYPE_ITEM = 0;
    private final int VIEW_TYPE_LOADING = 1;
    private boolean isRefreshing;


    public PodcastsAdapter(List<Podcast> podcasts, Podcast featuredPodcast, OnPodcastSelectedListener listener, MediaPlayerInterface mediaPlayerInterface) {
        this.mPodcasts = podcasts;
        this.featuredPodcast = featuredPodcast;
        this.mListener = listener;
        this.mediaPlayerInterface = mediaPlayerInterface;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        mediaPlayerInterface.subscribeToPlayerService(getServiceObserver());


        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        if (viewType == VIEW_TYPE_LOADING) {
            return new LoadingViewHolder(ItemLoadingBinding.inflate(inflater, parent, false));
        } else {
            return new PodcastsViewHolder(inflater.inflate(R.layout.item_podcast, parent, false));
        }


    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {

        if (viewHolder instanceof LoadingViewHolder) {
            LoadingViewHolder loadingViewHolder = (LoadingViewHolder) viewHolder;
            loadingViewHolder.binding.txtLoadingMore.setText(viewHolder.itemView.getContext().getString(R.string.loading_more_podcasts));
        } else {
            PodcastsViewHolder holder = (PodcastsViewHolder) viewHolder;
            Podcast mPodcast = mPodcasts.get(holder.getAdapterPosition());

            if (holder.getAdapterPosition() == 0 && featuredPodcast != null) {
                setFeaturedPodcast(featuredPodcast, holder);
                holder.svFeaturedPodcast.setVisibility(View.VISIBLE);
                final Download[] featuredDownload = {featuredPodcast.getDownload()};
                setDownloadState(featuredPodcast, featuredDownload, holder.featuredMusicIndicator, holder.imgFeaturedDownload, holder.txtFeaturedDownloadProgress, holder.pbFeaturedDownloadProgress);
            } else {
                holder.svFeaturedPodcast.setVisibility(View.GONE);
            }

            setPodcast(mPodcast, holder);

            final Download[] download = {mPodcast.getDownload()};
            setDownloadState(mPodcast, download, holder.musicIndicator, holder.imgDownload, holder.txtDownloadProgress, holder.pbDownloadProgress);
        }
    }

    private void setDownloadState(Podcast mPodcast, Download[] download, Indicator musicIndicator, ImageView imgDownload, TextView txtDownloadProgress, ProgressBar pbDownloadProgress) {

        /**
         * State precedence
         *
         * 1. Playing
         * 2. Downloading
         * 3. Downloaded
         * 4. Default
         */
        if ((mediaPlayerInterface.isQueued(mPodcast) && (mediaPlayerInterface.isPlaying()) || mPodcast.isPlaying())) {
            //Playing
            musicIndicator.setVisibility(View.VISIBLE);
            mPodcast.setPlaying(true);
            imgDownload.setVisibility(View.GONE);
            pbDownloadProgress.setVisibility(View.GONE);
            txtDownloadProgress.setVisibility(View.GONE);


        } else if (download[0] != null && (download[0].getStatus() == Status.DOWNLOADING ||
                download[0].getStatus() == Status.QUEUED ||
                download[0].getStatus() == Status.ADDED ||
                download[0].getStatus() == Status.PAUSED)) {
            //Downloading but not playing
            mPodcast.setPlaying(false);
            if (download[0].getProgress() < 0) {
                txtDownloadProgress.setText(String.format(Locale.getDefault(), "%d%%", 0));
            } else {
                txtDownloadProgress.setText(String.format(Locale.getDefault(), "%d%%", download[0].getProgress()));
            }

            musicIndicator.setVisibility(View.GONE);
            pbDownloadProgress.setVisibility(View.VISIBLE);
            ObjectAnimator.ofInt(pbDownloadProgress, "progress", download[0].getProgress())
                    .setDuration(300)
                    .start();

//            pbDownloadProgress.setProgress(download[0].getProgress());
            imgDownload.setVisibility(View.GONE);
            txtDownloadProgress.setVisibility(View.VISIBLE);


        } else if (mListener.isDownloaded(mPodcast.getPostId())) { //||
            //  (download[0] != null && (download[0].getStatus() == Status.COMPLETED || download[0].getProgress() >= 99))) {
            //Downloaded


            mPodcast.setPlaying(false);
            musicIndicator.setVisibility(View.GONE);

            imgDownload.setVisibility(View.GONE);
            pbDownloadProgress.setVisibility(View.GONE);
            txtDownloadProgress.setVisibility(View.GONE);

        } else {
            //Default
            mPodcast.setPlaying(false);
            musicIndicator.setVisibility(View.GONE);

            pbDownloadProgress.setVisibility(View.GONE);
            txtDownloadProgress.setVisibility(View.GONE);


            if (PrefUtils.getInstance().getBooleanPref(PrefKey.IS_GUEST_ACCOUNT)) {
                imgDownload.setVisibility(View.GONE);
            } else if (SubscriptionUtils.userCanAccessAudio(PrefUtils.getInstance().getSubs(), mPodcast)) {
                imgDownload.setVisibility(View.VISIBLE);
            } else {
                imgDownload.setVisibility(View.GONE);
            }

        }
    }

    @Override
    public int getItemCount() {
        return mPodcasts.size();
    }

    @Override
    public int getItemViewType(int position) {
        return mPodcasts.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
    }

    public void add(List<Podcast> podcasts) {
        removeLoader();
        int count = 0;
        for (Podcast podcast :
                podcasts) {
            if (podcast == null || podcast.getPodcastFullUrl() == null) {
                count++;
            }
        }
        Log.d("null count", String.valueOf(count));

        int oldSize = mPodcasts.size();
        if (podcasts != null) {
            mPodcasts.addAll(podcasts);
            notifyItemRangeInserted(oldSize, podcasts.size());
        }
    }

    private void removeLoader() {
        try {
            for (int i = 0; i < mPodcasts.size(); i++) {
                Podcast podcast = mPodcasts.get(i);
                if (podcast == null) {
                    mPodcasts.remove(i);
                    notifyItemRemoved(i);
                    i = 0;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            FirebaseCrashlytics.getInstance().recordException(e);
        }
        isRefreshing = false;
    }

    public void addLoader() {
        mPodcasts.add(null);
        isRefreshing = true;
        notifyItemInserted(mPodcasts.size() - 1);
    }

    public boolean isRefreshing() {
        return isRefreshing;
    }

    private void setFeaturedPodcast(Podcast podcast, PodcastsViewHolder holder) {
        GlideApp.with(holder.itemView.getContext()).load(podcast.getLargeImage()).placeholder(R.drawable.ic_placeholder_podcast_large).into(holder.imgFeaturedPodcast);
        holder.txtFeaturedPodcastTitle.setText(Html.fromHtml(podcast.getTitle()));

        if (podcast.isPurchased() || !SubscriptionUtils.userCanAccessAudio(PrefUtils.getInstance().getSubs(), podcast)) {
            holder.txtFeaturedPremium.setVisibility(View.VISIBLE);
        } else {
            holder.txtFeaturedPremium.setVisibility(View.GONE);
        }

        holder.imgFeaturedDownload.setOnClickListener(v -> {
            holder.imgFeaturedDownload.setVisibility(View.GONE);
            holder.pbFeaturedDownloadProgress.setVisibility(View.VISIBLE);
            mListener.onDownloadPodcastSelected(podcast, holder.getAdapterPosition());
        });

        if (podcast.isPurchased()) {
            holder.txtFeaturedPremium.setText(holder.itemView.getContext().getString(R.string.purchased));
            holder.txtFeaturedPremium.setBackgroundColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.grey9b9b9b));
        } else {
            holder.txtFeaturedPremium.setText(holder.itemView.getContext().getString(R.string.premium));
            holder.txtFeaturedPremium.setBackgroundColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.black1B1B1B));
        }

        holder.llFeaturedPodcastHeader.setOnClickListener(v -> mListener.onPodcastSelected(featuredPodcast));
        holder.txtFeaturedPodcastDate.setText(DateUtils.getDateddMMYYYY(podcast.getCreatedDate()));

        setMinsText(featuredPodcast, holder.txtFeaturedPodcastListenTime, holder.itemView.getContext());

        mediaPlayerInterface.getPodcastState(podcast.getPostId(), holder.getAdapterPosition(), (featuredPodcastState, position) -> {
            if (featuredPodcastState != null && featuredPodcastState.isValid() && SubscriptionUtils.userCanAccessAudio(PrefUtils.getInstance().getSubs(), podcast)) {
                holder.pbFeaturedPodcastProgress.setVisibility(View.VISIBLE);
                holder.pbFeaturedPodcastProgress.setMax((int) featuredPodcastState.getPodcastDuration());
                holder.pbFeaturedPodcastProgress.setProgress((int) featuredPodcastState.getPodcastPosition());
            } else {
                holder.pbFeaturedPodcastProgress.setVisibility(View.GONE);
            }
        });
    }

    private void setPodcast(Podcast mPodcast, PodcastsViewHolder holder) {

        setImage(mPodcast, holder.itemView.getContext(), holder.imgPodcast);

        holder.txtPodcastTitle.setText(Html.fromHtml(mPodcast.getTitle()));
        holder.txtPodcastDate.setText(DateUtils.getDateddMMYYYY(mPodcast.getCreatedDate()));
        setMinsText(mPodcast, holder.txtPodcastListenTime, holder.itemView.getContext());

        holder.llPodcastMain.setOnClickListener(v -> mListener.onPodcastSelected(mPodcast));

        holder.imgDownload.setOnClickListener(v -> {
            holder.imgDownload.setVisibility(View.GONE);
            holder.pbDownloadProgress.setVisibility(View.VISIBLE);
            mListener.onDownloadPodcastSelected(mPodcast, holder.getAdapterPosition());
        });

        if (SubscriptionUtils.userCanAccessAudio(PrefUtils.getInstance().getSubs(), mPodcast)) {
            holder.txtPremium.setVisibility(View.GONE);
        } else {
            holder.txtPremium.setVisibility(View.VISIBLE);
        }

        if (mPodcast.isPurchased()) {
            holder.txtPremium.setVisibility(View.VISIBLE);
            holder.txtPremium.setText(holder.itemView.getContext().getString(R.string.purchased));
            holder.txtPremium.setBackgroundColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.grey9b9b9b));
        } else {
            holder.txtPremium.setText(holder.itemView.getContext().getString(R.string.premium));
            holder.txtPremium.setBackgroundColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.black1B1B1B));
        }


        mediaPlayerInterface.getPodcastState(mPodcast.getPostId(), holder.getAdapterPosition(), (podcastState, position) -> {
            if (podcastState != null && podcastState.isValid() && SubscriptionUtils.userCanAccessAudio(PrefUtils.getInstance().getSubs(), mPodcast)) {
                holder.pbPodcastProgress.setVisibility(View.VISIBLE);
                holder.pbPodcastProgress.setMax((int) podcastState.getPodcastDuration());
                holder.pbPodcastProgress.setProgress((int) podcastState.getPodcastPosition());
            } else {
                holder.pbPodcastProgress.setVisibility(View.GONE);
            }
            //TODO stop UI stutter

//            notifyItemChanged(position);
        });


    }

    private void setImage(Podcast mPodcast, Context context, RoundedImageView imageView) {
        String imageUrl = "";

        if (mPodcast != null) {
            if (mPodcast.getThumbnail() != null && !mPodcast.getThumbnail().equals("")) {
                imageUrl = mPodcast.getThumbnail();
            } else if (mPodcast.getMediumImage() != null && !mPodcast.getMediumImage().equals("")) {
                imageUrl = mPodcast.getMediumImage();
            } else if (mPodcast.getLargeImage() != null && !mPodcast.getLargeImage().equals("")) {
                imageUrl = mPodcast.getLargeImage();
            }

        }

        if (imageUrl.equals("")) {
            imageView.setImageResource(R.drawable.ic_placeholder_podcast_small);
        } else {
            GlideApp.with(context)
                    .load(imageUrl)
                    .placeholder(R.drawable.ic_placeholder_podcast_small)
                    .into(imageView);
        }

    }

    private void setMinsText(Podcast podcast, TextView textView, Context context) {
        try {
            textView.setText(String.format(context.getString(R.string.mins_param), podcast.getPodcastLength()));
        } catch (Exception e) {
            e.printStackTrace();
            textView.setVisibility(View.GONE);
        }
    }

    public void addDownload(@NonNull final Download download) {
        if (featuredPodcast.getPodcastFullUrl().equals(download.getUrl())) {
            featuredPodcast.setDownload(download);
        }

        for (int i = 0; i < mPodcasts.size(); i++) {
            if (mPodcasts.get(i).getPodcastFullUrl().equals(download.getUrl())) {
                mPodcasts.get(i).setDownload(download);
                break;
            }
        }
    }

    public void update(@NonNull final Download download) {

        if (featuredPodcast.getPodcastFullUrl().equals(download.getUrl())) {
            switch (download.getStatus()) {
                case REMOVED:
                case FAILED:
                case CANCELLED:
                case DELETED: {
                    featuredPodcast.setDownload(null);
                    notifyItemChanged(0);
                    break;
                }
                default: {
                    featuredPodcast.setDownload(download);
                    notifyItemChanged(0);
                    break;
                }
            }
        }


        for (int i = 0; i < mPodcasts.size(); i++) {

            Podcast podcast = mPodcasts.get(i);

            if (podcast.getPodcastFullUrl().equals(download.getUrl())) {

                switch (download.getStatus()) {
                    case REMOVED:
                    case FAILED:
                    case CANCELLED:
                    case DELETED: {
                        mPodcasts.get(i).setDownload(null);
                        notifyItemChanged(i);
                        break;
                    }
                    default: {
                        mPodcasts.get(i).setDownload(download);
                        notifyItemChanged(i);
                        break;
                    }
                }
                break;
            }
        }
    }

    public void onDownloadCompleted(Download download) {


        if (featuredPodcast.getPodcastFullUrl().equals(download.getUrl())) {
            mListener.savePodcast(featuredPodcast, download);
        }

        for (int i = 0; i < mPodcasts.size(); i++) {
            try {
                if (mPodcasts.get(i).getPodcastFullUrl().equals(download.getUrl())) {
                    mListener.savePodcast(mPodcasts.get(i), download);
                    break;
                }
            } catch (NullPointerException e) {
                FirebaseCrashlytics.getInstance().log("Tried to save podcast with null data at position " + i + " for download " + download.getUrl());
                throw e;
            }
        }
    }

    private Observer<String> getServiceObserver() {
        if (serviceObserver != null) {
            return serviceObserver;
        }

        serviceObserver = new Observer<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {
                e.printStackTrace();
            }

            @Override
            public void onNext(String s) {
                Podcast savedPodcast = PodcastStorageUtil.getInstance().loadAudio();

                Log.d("POD ADAPTER", s);

                checkPodcastPlaying(s, featuredPodcast, savedPodcast, 0, true);

                for (int i = 0; i < mPodcasts.size(); i++) {
                    Podcast mPodcast = mPodcasts.get(i);
                    checkPodcastPlaying(s, mPodcast, savedPodcast, i, false);
                }
            }
        };

        return serviceObserver;
    }

    private void checkPodcastPlaying(String s, Podcast podcast, Podcast savedPodcast, int posi, boolean isFeatured) {
        switch (s) {
            case MediaConstants.RX_PLAY:
                if (savedPodcast != null && savedPodcast.getPostId().equals(podcast.getPostId())) {
                    if (isFeatured) {
                        updateFeaturedPlayingStateUI(true);
                    } else {
                        updatePlayingStateUI(posi, true);
                    }

                }
                break;
            case MediaConstants.RX_PAUSE:
            case MediaConstants.RX_COMPLETE:
            case MediaConstants.RX_STOP:
                if (isFeatured) {
                    updateFeaturedPlayingStateUI(false);
                } else {
                    updatePlayingStateUI(posi, false);
                }

                break;

        }
        notifyItemChanged(posi);

    }

    private void updateFeaturedPlayingStateUI(boolean isPlaying) {
        featuredPodcast.setPlaying(isPlaying);
        notifyItemChanged(0);
    }

    private void updatePlayingStateUI(int position, boolean isPlaying) {
        Podcast mPodcast = mPodcasts.get(position);
        mPodcast.setPlaying(isPlaying);
        notifyItemChanged(position);
    }

    public class PodcastsViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.ll_podcast_main)
        LinearLayout llPodcastMain;
        @BindView(R.id.img_podcast)
        RoundedImageView imgPodcast;
        @BindView(R.id.txt_premium)
        TextView txtPremium;
        @BindView(R.id.txt_podcast_date)
        TextView txtPodcastDate;
        @BindView(R.id.txt_podcast_listen_time)
        TextView txtPodcastListenTime;
        @BindView(R.id.txt_podcast_title)
        TextView txtPodcastTitle;
        @BindView(R.id.img_download)
        ImageView imgDownload;
        @BindView(R.id.music_indicator)
        Indicator musicIndicator;
        @BindView(R.id.pb_podcast_progress)
        ProgressBar pbPodcastProgress;


        @BindView(R.id.featured_music_indicator)
        Indicator featuredMusicIndicator;
        @BindView(R.id.img_featured_download)
        ImageView imgFeaturedDownload;


        @BindView(R.id.rl_download_container)
        RelativeLayout rlDownloadContainer;
        @BindView(R.id.pb_download_progress)
        ProgressBar pbDownloadProgress;
        @BindView(R.id.txt_download_progress)
        TextView txtDownloadProgress;

        @BindView(R.id.rl_featured_download_container)
        RelativeLayout rlFeaturedDownloadContainer;
        @BindView(R.id.pb_featured_download_progress)
        ProgressBar pbFeaturedDownloadProgress;
        @BindView(R.id.txt_featured_download_progress)
        TextView txtFeaturedDownloadProgress;


        @BindView(R.id.sv_featured_podcast)
        ShadowView svFeaturedPodcast;
        @BindView(R.id.img_featured_podcast)
        RoundedImageView imgFeaturedPodcast;
        @BindView(R.id.txt_featured)
        TextView txtFeatured;

        @BindView(R.id.txt_featured_premium)
        TextView txtFeaturedPremium;
        @BindView(R.id.txt_featured_podcast_title)
        TextView txtFeaturedPodcastTitle;
        @BindView(R.id.txt_featured_podcast_date)
        TextView txtFeaturedPodcastDate;
        @BindView(R.id.txt_featured_podcast_listen_time)
        TextView txtFeaturedPodcastListenTime;
        @BindView(R.id.ll_featured_podcast_header)
        LinearLayout llFeaturedPodcastHeader;
        @BindView(R.id.pb_featured_podcast_progress)
        ProgressBar pbFeaturedPodcastProgress;

        public PodcastsViewHolder(@NonNull View itemView) {
            super(itemView);

            ButterKnife.bind(this, itemView);
            setFonts();
        }

        private void setFonts() {
            txtPremium.setTypeface(FontUtils.getInstance().getDinAlternateBold());
            txtPodcastDate.setTypeface(FontUtils.getInstance().getDinAlternateBold());
            txtPodcastListenTime.setTypeface(FontUtils.getInstance().getDinAlternateBold());
            txtPodcastTitle.setTypeface(FontUtils.getInstance().getDinAlternateBold());
            txtDownloadProgress.setTypeface(FontUtils.getInstance().getDinAlternateBold());

            txtFeatured.setTypeface(FontUtils.getInstance().getDinAlternateBold());
            txtFeaturedPremium.setTypeface(FontUtils.getInstance().getDinAlternateBold());
            txtFeaturedPodcastTitle.setTypeface(FontUtils.getInstance().getDinAlternateBold());
            txtFeaturedPodcastDate.setTypeface(FontUtils.getInstance().getDinAlternateBold());
            txtFeaturedPodcastListenTime.setTypeface(FontUtils.getInstance().getDinAlternateBold());
        }
    }
}
