/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.support.v17.leanback.supportleanbackshowcase.app.room.di.listener;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v17.leanback.app.BackgroundManager;
import android.support.v17.leanback.supportleanbackshowcase.app.room.controller.detail.LiveDataDetailActivity;
import android.support.v17.leanback.supportleanbackshowcase.app.room.controller.detail.LiveDataDetailViewWithVideoBackgroundFragment;
import android.support.v17.leanback.supportleanbackshowcase.app.room.controller.overview.LiveDataFragment;
import android.support.v17.leanback.supportleanbackshowcase.app.room.controller.search.SearchActivity;
import android.support.v17.leanback.supportleanbackshowcase.app.room.controller.search.SearchFragment;
import android.support.v17.leanback.supportleanbackshowcase.app.room.db.entity.VideoEntity;
import android.support.v17.leanback.supportleanbackshowcase.app.room.di.scope.PerFragment;
import android.support.v17.leanback.widget.ImageCardView;
import android.support.v17.leanback.widget.OnItemViewClickedListener;
import android.support.v17.leanback.widget.OnItemViewSelectedListener;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.Row;
import android.support.v17.leanback.widget.RowPresenter;
import android.support.v4.app.ActivityOptionsCompat;
import android.util.DisplayMetrics;
import android.view.View;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;

@Module
public class ListenerModule {

    private static final int BACKGROUND_UPDATE_DELAY = 300;

    private RunnableClass lastTime;

    @PerFragment
    @Provides
    @IntoMap
    @ListenerModuleKey(LiveDataFragment.class)
    public OnItemViewClickedListener provideOnItemViewClickListenerForLiveDataFragment(
            final Activity currentActivity) {
        return new OnItemViewClickedListener() {
            @Override
            public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
                    RowPresenter.ViewHolder rowViewHolder, Row row) {
                Intent intent;
                Long videoItemId = ((VideoEntity) item).getId();
                intent = new Intent(currentActivity, LiveDataDetailActivity.class);
                intent.putExtra(LiveDataDetailActivity.VIDEO_ID, videoItemId);

                VideoEntity cachedBundle = (VideoEntity) item;

                intent.putExtra(LiveDataDetailActivity.CACHED_CONTENT, cachedBundle);

                // enable the scene transition animation when the detail's activity is launched
                Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
                        currentActivity,
                        ((ImageCardView) itemViewHolder.view).getMainImageView(),
                        LiveDataDetailActivity.SHARED_ELEMENT_NAME).toBundle();
                currentActivity.startActivity(intent, bundle);
            }
        };
    }

    @PerFragment
    @Provides
    @IntoMap
    @ListenerModuleKey(SearchFragment.class)
    public OnItemViewClickedListener provideOnItemViewClickListenerForLiveDataDetailFragmentSearch(
            final Activity currentActivity) {
        return new OnItemViewClickedListener() {
            @Override
            public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
                    RowPresenter.ViewHolder rowViewHolder, Row row) {
                if (item instanceof VideoEntity) {
                    Intent intent;
                    Long videoItemId = ((VideoEntity) item).getId();
                    intent = new Intent(currentActivity, LiveDataDetailActivity.class);
                    intent.putExtra(LiveDataDetailActivity.VIDEO_ID, videoItemId);

                    VideoEntity cachedBundle = (VideoEntity) item;

                    intent.putExtra(LiveDataDetailActivity.CACHED_CONTENT, cachedBundle);

                    // enable the scene transition animation when the detail's activity is launched
                    Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
                            currentActivity,
                            ((ImageCardView) itemViewHolder.view).getMainImageView(),
                            LiveDataDetailActivity.SHARED_ELEMENT_NAME).toBundle();
                    currentActivity.startActivity(intent, bundle);
                }
            }
        };
    }

    @PerFragment
    @Provides
    @IntoMap
    @ListenerModuleKey(LiveDataDetailViewWithVideoBackgroundFragment.class)
    public OnItemViewClickedListener provideOnItemViewClickListenerForLiveDataDetailFragment(
            final Activity currentActivity) {
        return new OnItemViewClickedListener() {
            @Override
            public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
                    RowPresenter.ViewHolder rowViewHolder, Row row) {
                if (item instanceof VideoEntity) {
                    Intent intent;
                    Long videoItemId = ((VideoEntity) item).getId();
                    intent = new Intent(currentActivity, LiveDataDetailActivity.class);
                    intent.putExtra(LiveDataDetailActivity.VIDEO_ID, videoItemId);

                    VideoEntity cachedBundle = (VideoEntity) item;

                    intent.putExtra(LiveDataDetailActivity.CACHED_CONTENT, cachedBundle);

                    // enable the scene transition animation when the detail's activity is launched
                    Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
                            currentActivity,
                            ((ImageCardView) itemViewHolder.view).getMainImageView(),
                            LiveDataDetailActivity.SHARED_ELEMENT_NAME).toBundle();
                    currentActivity.startActivity(intent, bundle);
                }
            }
        };
    }


    @PerFragment
    @Provides
    public Handler provideMainThreadHandler() {
        return new Handler(Looper.getMainLooper());
    }

    @PerFragment
    @Provides
    @IntoMap
    @ListenerModuleKey(LiveDataFragment.class)
    public OnItemViewSelectedListener provideOnItemViewSelectedListener(final Activity activity,
            final DisplayMetrics metrics, final BackgroundManager backgroundManager,
            final RequestOptions defaultPlaceHolder, final Drawable finalDrawable, final Handler mainHandler) {
        return new OnItemViewSelectedListener() {
            @Override
            public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
                    RowPresenter.ViewHolder rowViewHolder, Row row) {
                VideoEntity selectedVideo = (VideoEntity) item;
                RunnableClass backgroundRunnable = new RunnableClass(selectedVideo, activity,
                        metrics, backgroundManager, defaultPlaceHolder, finalDrawable);

                if (lastTime != null) {
                    mainHandler.removeCallbacks(lastTime);
                }
                mainHandler.postDelayed(backgroundRunnable, BACKGROUND_UPDATE_DELAY);
                lastTime = backgroundRunnable;
            }
        };
    }

    @PerFragment
    @Provides
    @IntoMap
    @ListenerModuleKey(LiveDataFragment.class)
    public View.OnClickListener provideOnClickSearchButtonListener(final Activity currentActivity) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(currentActivity, SearchActivity.class);
                currentActivity.startActivity(intent);
            }
        };
    }

    /**
     * Define this runnable class explicitly so it can take dependency injected parameter to
     * construct the runnable object for execution
     */
    private class RunnableClass implements Runnable {

        private VideoEntity mSelectedVideo;
        private Activity mActivity;
        private DisplayMetrics mDisplayMetrics;
        private BackgroundManager mBackgroundManager;
        private RequestOptions mDefaultPlaceHolder;
        private Drawable mDrawable;

        public RunnableClass(VideoEntity selectedVideo, final Activity activity,
                DisplayMetrics metrics, BackgroundManager backgroundManager,
                RequestOptions defaultPlaceHolder, final Drawable drawable) {
            mSelectedVideo = selectedVideo;
            mActivity = activity;
            mDisplayMetrics = metrics;
            mBackgroundManager = backgroundManager;
            mDefaultPlaceHolder = defaultPlaceHolder;
            mDrawable = drawable;
        }

        @Override
        public void run() {
            loadAndSetBackgroundImageParameter(mSelectedVideo, mActivity, mDisplayMetrics,
                    mBackgroundManager, mDefaultPlaceHolder, mDrawable);
        }
    }

    private void loadAndSetBackgroundImageParameter(VideoEntity selectedVideo,
            final Activity activity, DisplayMetrics metrics,
            final BackgroundManager backgroundManager, RequestOptions defaultPlaceHolder,
            Drawable defualtDrawble) {
        if (selectedVideo == null) {
            return;
        }
        String url1 = selectedVideo.getVideoBgImageLocalStorageUrl();
        String url2 = selectedVideo.getBgImageUrl();
        String loadedUri;
        if (url1.isEmpty()) {
            loadedUri = url2;
        } else {
            loadedUri = url1;
        }

        // wait until runtime the activity has window
        if (!backgroundManager.isAttached()) {
            backgroundManager.attach(activity.getWindow());
        }

        // glide on error
        Glide.with(activity)
                .asBitmap()
                .load(loadedUri)
                .apply(defaultPlaceHolder)
                .into(new SimpleTarget<Bitmap>(metrics.widthPixels, metrics.heightPixels) {
                    @Override
                    public void onResourceReady(Bitmap resource,
                            Transition<? super Bitmap> glideAnimation) {
                        backgroundManager.setDrawable(
                                new BitmapDrawable(activity.getResources(), resource));
                    }
                });
    }
}