/*
 * Copyright (C) 2015 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 com.android.tv.recommendation;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.tv.TvInputInfo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseLongArray;
import android.view.View;
import com.android.tv.MainActivityWrapper.OnCurrentChannelChangeListener;
import com.android.tv.R;
import com.android.tv.Starter;
import com.android.tv.TvSingletons;
import com.android.tv.common.CommonConstants;
import com.android.tv.common.WeakHandler;
import com.android.tv.data.Program;
import com.android.tv.data.api.Channel;
import com.android.tv.util.TvInputManagerHelper;
import com.android.tv.util.Utils;
import com.android.tv.util.images.BitmapUtils;
import com.android.tv.util.images.BitmapUtils.ScaledBitmapInfo;
import com.android.tv.util.images.ImageLoader;
import java.util.ArrayList;
import java.util.List;

/** A local service for notify recommendation at home launcher. */
public class NotificationService extends Service
        implements Recommender.Listener, OnCurrentChannelChangeListener {
    private static final String TAG = "NotificationService";
    private static final boolean DEBUG = false;

    public static final String ACTION_SHOW_RECOMMENDATION =
            CommonConstants.BASE_PACKAGE + ".notification.ACTION_SHOW_RECOMMENDATION";
    public static final String ACTION_HIDE_RECOMMENDATION =
            CommonConstants.BASE_PACKAGE + ".notification.ACTION_HIDE_RECOMMENDATION";

    /**
     * Recommendation intent has an extra data for the recommendation type. It'll be also sent to a
     * TV input as a tune parameter.
     */
    public static final String TUNE_PARAMS_RECOMMENDATION_TYPE =
            CommonConstants.BASE_PACKAGE + ".recommendation_type";

    private static final String TYPE_RANDOM_RECOMMENDATION = "random";
    private static final String TYPE_ROUTINE_WATCH_RECOMMENDATION = "routine_watch";
    private static final String TYPE_ROUTINE_WATCH_AND_FAVORITE_CHANNEL_RECOMMENDATION =
            "routine_watch_and_favorite";

    private static final String NOTIFY_TAG = "tv_recommendation";
    // TODO: find out proper number of notifications and whether to make it dynamically
    // configurable from system property or etc.
    private static final int NOTIFICATION_COUNT = 3;

    private static final int MSG_INITIALIZE_RECOMMENDER = 1000;
    private static final int MSG_SHOW_RECOMMENDATION = 1001;
    private static final int MSG_UPDATE_RECOMMENDATION = 1002;
    private static final int MSG_HIDE_RECOMMENDATION = 1003;

    private static final long RECOMMENDATION_RETRY_TIME_MS = 5 * 60 * 1000; // 5 min
    private static final long RECOMMENDATION_THRESHOLD_LEFT_TIME_MS = 10 * 60 * 1000; // 10 min
    private static final int RECOMMENDATION_THRESHOLD_PROGRESS = 90; // 90%
    private static final int MAX_PROGRAM_UPDATE_COUNT = 20;

    private TvInputManagerHelper mTvInputManagerHelper;
    private Recommender mRecommender;
    private boolean mShowRecommendationAfterRecommenderReady;
    private NotificationManager mNotificationManager;
    private HandlerThread mHandlerThread;
    private Handler mHandler;
    private final String mRecommendationType;
    private int mCurrentNotificationCount;
    private long[] mNotificationChannels;

    private Channel mPlayingChannel;

    private float mNotificationCardMaxWidth;
    private float mNotificationCardHeight;
    private int mCardImageHeight;
    private int mCardImageMaxWidth;
    private int mCardImageMinWidth;
    private int mChannelLogoMaxWidth;
    private int mChannelLogoMaxHeight;
    private int mLogoPaddingStart;
    private int mLogoPaddingBottom;

    public NotificationService() {
        mRecommendationType = TYPE_ROUTINE_WATCH_AND_FAVORITE_CHANNEL_RECOMMENDATION;
    }

    @Override
    public void onCreate() {
        if (DEBUG) Log.d(TAG, "onCreate");
        Starter.start(this);
        super.onCreate();
        mCurrentNotificationCount = 0;
        mNotificationChannels = new long[NOTIFICATION_COUNT];
        for (int i = 0; i < NOTIFICATION_COUNT; ++i) {
            mNotificationChannels[i] = Channel.INVALID_ID;
        }
        mNotificationCardMaxWidth =
                getResources().getDimensionPixelSize(R.dimen.notif_card_img_max_width);
        mNotificationCardHeight =
                getResources().getDimensionPixelSize(R.dimen.notif_card_img_height);
        mCardImageHeight = getResources().getDimensionPixelSize(R.dimen.notif_card_img_height);
        mCardImageMaxWidth = getResources().getDimensionPixelSize(R.dimen.notif_card_img_max_width);
        mCardImageMinWidth = getResources().getDimensionPixelSize(R.dimen.notif_card_img_min_width);
        mChannelLogoMaxWidth =
                getResources().getDimensionPixelSize(R.dimen.notif_ch_logo_max_width);
        mChannelLogoMaxHeight =
                getResources().getDimensionPixelSize(R.dimen.notif_ch_logo_max_height);
        mLogoPaddingStart =
                getResources().getDimensionPixelOffset(R.dimen.notif_ch_logo_padding_start);
        mLogoPaddingBottom =
                getResources().getDimensionPixelOffset(R.dimen.notif_ch_logo_padding_bottom);

        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        TvSingletons tvSingletons = TvSingletons.getSingletons(this);
        mTvInputManagerHelper = tvSingletons.getTvInputManagerHelper();
        mHandlerThread = new HandlerThread("tv notification");
        mHandlerThread.start();
        mHandler = new NotificationHandler(mHandlerThread.getLooper(), this);
        mHandler.sendEmptyMessage(MSG_INITIALIZE_RECOMMENDER);

        // Just called for early initialization.
        tvSingletons.getChannelDataManager();
        tvSingletons.getProgramDataManager();
        tvSingletons.getMainActivityWrapper().addOnCurrentChannelChangeListener(this);
    }

    @UiThread
    @Override
    public void onCurrentChannelChange(@Nullable Channel channel) {
        if (DEBUG) Log.d(TAG, "onCurrentChannelChange");
        mPlayingChannel = channel;
        mHandler.removeMessages(MSG_SHOW_RECOMMENDATION);
        mHandler.sendEmptyMessage(MSG_SHOW_RECOMMENDATION);
    }

    private void handleInitializeRecommender() {
        mRecommender = new Recommender(NotificationService.this, NotificationService.this, true);
        if (TYPE_RANDOM_RECOMMENDATION.equals(mRecommendationType)) {
            mRecommender.registerEvaluator(new RandomEvaluator());
        } else if (TYPE_ROUTINE_WATCH_RECOMMENDATION.equals(mRecommendationType)) {
            mRecommender.registerEvaluator(new RoutineWatchEvaluator());
        } else if (TYPE_ROUTINE_WATCH_AND_FAVORITE_CHANNEL_RECOMMENDATION.equals(
                mRecommendationType)) {
            mRecommender.registerEvaluator(new FavoriteChannelEvaluator(), 0.5, 0.5);
            mRecommender.registerEvaluator(new RoutineWatchEvaluator(), 1.0, 1.0);
        } else {
            throw new IllegalStateException(
                    "Undefined recommendation type: " + mRecommendationType);
        }
    }

    private void handleShowRecommendation() {
        if (mRecommender == null) {
            return;
        }
        if (!mRecommender.isReady()) {
            mShowRecommendationAfterRecommenderReady = true;
        } else {
            showRecommendation();
        }
    }

    private void handleUpdateRecommendation(int notificationId, Channel channel) {
        if (mNotificationChannels[notificationId] == Channel.INVALID_ID
                || !sendNotification(channel.getId(), notificationId)) {
            changeRecommendation(notificationId);
        }
    }

    private void handleHideRecommendation() {
        if (mRecommender == null) {
            return;
        }
        if (!mRecommender.isReady()) {
            mShowRecommendationAfterRecommenderReady = false;
        } else {
            hideAllRecommendation();
        }
    }

    @Override
    public void onDestroy() {
        TvSingletons.getSingletons(this)
                .getMainActivityWrapper()
                .removeOnCurrentChannelChangeListener(this);
        if (mRecommender != null) {
            mRecommender.release();
            mRecommender = null;
        }
        if (mHandlerThread != null) {
            mHandlerThread.quit();
            mHandlerThread = null;
            mHandler = null;
        }
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (DEBUG) Log.d(TAG, "onStartCommand");
        if (intent != null) {
            String action = intent.getAction();
            if (ACTION_SHOW_RECOMMENDATION.equals(action)) {
                mHandler.removeMessages(MSG_SHOW_RECOMMENDATION);
                mHandler.removeMessages(MSG_HIDE_RECOMMENDATION);
                mHandler.obtainMessage(MSG_SHOW_RECOMMENDATION).sendToTarget();
            } else if (ACTION_HIDE_RECOMMENDATION.equals(action)) {
                mHandler.removeMessages(MSG_SHOW_RECOMMENDATION);
                mHandler.removeMessages(MSG_UPDATE_RECOMMENDATION);
                mHandler.removeMessages(MSG_HIDE_RECOMMENDATION);
                mHandler.obtainMessage(MSG_HIDE_RECOMMENDATION).sendToTarget();
            }
        }
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onRecommenderReady() {
        if (DEBUG) Log.d(TAG, "onRecommendationReady");
        if (mShowRecommendationAfterRecommenderReady) {
            mHandler.removeMessages(MSG_SHOW_RECOMMENDATION);
            mHandler.sendEmptyMessage(MSG_SHOW_RECOMMENDATION);
            mShowRecommendationAfterRecommenderReady = false;
        }
    }

    @Override
    public void onRecommendationChanged() {
        if (DEBUG) Log.d(TAG, "onRecommendationChanged");
        // Update recommendation on the handler thread.
        mHandler.removeMessages(MSG_SHOW_RECOMMENDATION);
        mHandler.sendEmptyMessage(MSG_SHOW_RECOMMENDATION);
    }

    private void showRecommendation() {
        if (DEBUG) Log.d(TAG, "showRecommendation");
        SparseLongArray notificationChannels = new SparseLongArray();
        for (int i = 0; i < NOTIFICATION_COUNT; ++i) {
            if (mNotificationChannels[i] == Channel.INVALID_ID) {
                continue;
            }
            notificationChannels.put(i, mNotificationChannels[i]);
        }
        List<Channel> channels = recommendChannels();
        for (Channel c : channels) {
            int index = notificationChannels.indexOfValue(c.getId());
            if (index >= 0) {
                notificationChannels.removeAt(index);
            }
        }
        // Cancel notification whose channels are not recommended anymore.
        if (notificationChannels.size() > 0) {
            for (int i = 0; i < notificationChannels.size(); ++i) {
                int notificationId = notificationChannels.keyAt(i);
                mNotificationManager.cancel(NOTIFY_TAG, notificationId);
                mNotificationChannels[notificationId] = Channel.INVALID_ID;
                --mCurrentNotificationCount;
            }
        }
        for (Channel c : channels) {
            if (mCurrentNotificationCount >= NOTIFICATION_COUNT) {
                break;
            }
            if (!isNotifiedChannel(c.getId())) {
                sendNotification(c.getId(), getAvailableNotificationId());
            }
        }
        if (mCurrentNotificationCount < NOTIFICATION_COUNT) {
            mHandler.sendEmptyMessageDelayed(MSG_SHOW_RECOMMENDATION, RECOMMENDATION_RETRY_TIME_MS);
        }
    }

    private void changeRecommendation(int notificationId) {
        if (DEBUG) Log.d(TAG, "changeRecommendation");
        List<Channel> channels = recommendChannels();
        if (mNotificationChannels[notificationId] != Channel.INVALID_ID) {
            mNotificationChannels[notificationId] = Channel.INVALID_ID;
            --mCurrentNotificationCount;
        }
        for (Channel c : channels) {
            if (!isNotifiedChannel(c.getId())) {
                if (sendNotification(c.getId(), notificationId)) {
                    return;
                }
            }
        }
        mNotificationManager.cancel(NOTIFY_TAG, notificationId);
    }

    private List<Channel> recommendChannels() {
        List channels = mRecommender.recommendChannels();
        if (channels.contains(mPlayingChannel)) {
            channels = new ArrayList<>(channels);
            channels.remove(mPlayingChannel);
        }
        return channels;
    }

    private void hideAllRecommendation() {
        for (int i = 0; i < NOTIFICATION_COUNT; ++i) {
            if (mNotificationChannels[i] != Channel.INVALID_ID) {
                mNotificationChannels[i] = Channel.INVALID_ID;
                mNotificationManager.cancel(NOTIFY_TAG, i);
            }
        }
        mCurrentNotificationCount = 0;
    }

    private boolean sendNotification(final long channelId, final int notificationId) {
        final ChannelRecord cr = mRecommender.getChannelRecord(channelId);
        if (cr == null) {
            return false;
        }
        final Channel channel = cr.getChannel();
        if (DEBUG) {
            Log.d(
                    TAG,
                    "sendNotification (channelName="
                            + channel.getDisplayName()
                            + " notifyId="
                            + notificationId
                            + ")");
        }

        // TODO: Move some checking logic into TvRecommendation.
        String inputId = Utils.getInputIdForChannel(this, channel.getId());
        if (TextUtils.isEmpty(inputId)) {
            return false;
        }
        TvInputInfo inputInfo = mTvInputManagerHelper.getTvInputInfo(inputId);
        if (inputInfo == null) {
            return false;
        }

        final Program program = Utils.getCurrentProgram(this, channel.getId());
        if (program == null) {
            return false;
        }
        final long programDurationMs =
                program.getEndTimeUtcMillis() - program.getStartTimeUtcMillis();
        long programLeftTimsMs = program.getEndTimeUtcMillis() - System.currentTimeMillis();
        final int programProgress =
                (programDurationMs <= 0)
                        ? -1
                        : 100 - (int) (programLeftTimsMs * 100 / programDurationMs);

        // We recommend those programs that meet the condition only.
        if (programProgress >= RECOMMENDATION_THRESHOLD_PROGRESS
                && programLeftTimsMs <= RECOMMENDATION_THRESHOLD_LEFT_TIME_MS) {
            return false;
        }

        // We don't trust TIS to provide us with proper sized image
        ScaledBitmapInfo posterArtBitmapInfo =
                BitmapUtils.decodeSampledBitmapFromUriString(
                        this,
                        program.getPosterArtUri(),
                        (int) mNotificationCardMaxWidth,
                        (int) mNotificationCardHeight);
        if (posterArtBitmapInfo == null) {
            Log.e(TAG, "Failed to decode poster image for " + program.getPosterArtUri());
            return false;
        }
        final Bitmap posterArtBitmap = posterArtBitmapInfo.bitmap;

        channel.loadBitmap(
                this,
                Channel.LOAD_IMAGE_TYPE_CHANNEL_LOGO,
                mChannelLogoMaxWidth,
                mChannelLogoMaxHeight,
                createChannelLogoCallback(this, notificationId, channel, program, posterArtBitmap));

        if (mNotificationChannels[notificationId] == Channel.INVALID_ID) {
            ++mCurrentNotificationCount;
        }
        mNotificationChannels[notificationId] = channel.getId();

        return true;
    }

    private void sendNotification(
            int notificationId,
            Bitmap channelLogo,
            Channel channel,
            Bitmap posterArtBitmap,
            Program program) {
        final long programDurationMs =
                program.getEndTimeUtcMillis() - program.getStartTimeUtcMillis();
        long programLeftTimsMs = program.getEndTimeUtcMillis() - System.currentTimeMillis();
        final int programProgress =
                (programDurationMs <= 0)
                        ? -1
                        : 100 - (int) (programLeftTimsMs * 100 / programDurationMs);
        Intent intent = new Intent(Intent.ACTION_VIEW, channel.getUri());
        intent.putExtra(TUNE_PARAMS_RECOMMENDATION_TYPE, mRecommendationType);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        final PendingIntent notificationIntent = PendingIntent.getActivity(this, 0, intent, 0);

        // This callback will run on the main thread.
        Bitmap largeIconBitmap =
                (channelLogo == null)
                        ? posterArtBitmap
                        : overlayChannelLogo(channelLogo, posterArtBitmap);
        String channelDisplayName = channel.getDisplayName();
        Notification notification =
                new Notification.Builder(this)
                        .setContentIntent(notificationIntent)
                        .setContentTitle(program.getTitle())
                        .setContentText(
                                TextUtils.isEmpty(channelDisplayName)
                                        ? channel.getDisplayNumber()
                                        : channelDisplayName)
                        .setContentInfo(channelDisplayName)
                        .setAutoCancel(true)
                        .setLargeIcon(largeIconBitmap)
                        .setSmallIcon(R.drawable.ic_launcher_s)
                        .setCategory(Notification.CATEGORY_RECOMMENDATION)
                        .setProgress((programProgress > 0) ? 100 : 0, programProgress, false)
                        .setSortKey(mRecommender.getChannelSortKey(channel.getId()))
                        .build();
        notification.color = getResources().getColor(R.color.recommendation_card_background, null);
        if (!TextUtils.isEmpty(program.getThumbnailUri())) {
            notification.extras.putString(
                    Notification.EXTRA_BACKGROUND_IMAGE_URI, program.getThumbnailUri());
        }
        mNotificationManager.notify(NOTIFY_TAG, notificationId, notification);
        Message msg = mHandler.obtainMessage(MSG_UPDATE_RECOMMENDATION, notificationId, 0, channel);
        mHandler.sendMessageDelayed(msg, programDurationMs / MAX_PROGRAM_UPDATE_COUNT);
    }

    @NonNull
    private static ImageLoader.ImageLoaderCallback<NotificationService> createChannelLogoCallback(
            NotificationService service,
            final int notificationId,
            final Channel channel,
            final Program program,
            final Bitmap posterArtBitmap) {
        return new ImageLoader.ImageLoaderCallback<NotificationService>(service) {
            @Override
            public void onBitmapLoaded(NotificationService service, Bitmap channelLogo) {
                service.sendNotification(
                        notificationId, channelLogo, channel, posterArtBitmap, program);
            }
        };
    }

    private Bitmap overlayChannelLogo(Bitmap logo, Bitmap background) {
        Bitmap result =
                BitmapUtils.getScaledMutableBitmap(background, Integer.MAX_VALUE, mCardImageHeight);
        Bitmap scaledLogo =
                BitmapUtils.scaleBitmap(logo, mChannelLogoMaxWidth, mChannelLogoMaxHeight);
        Canvas canvas;
        try {
            canvas = new Canvas(result);
        } catch (Exception e) {
            Log.w(TAG, "Failed to create Canvas", e);
            return background;
        }
        canvas.drawBitmap(result, new Matrix(), null);
        Rect rect = new Rect();
        int startPadding;
        if (result.getWidth() < mCardImageMinWidth) {
            // TODO: check the positions.
            startPadding = mLogoPaddingStart;
            rect.bottom = result.getHeight() - mLogoPaddingBottom;
            rect.top = rect.bottom - scaledLogo.getHeight();
        } else if (result.getWidth() < mCardImageMaxWidth) {
            startPadding = mLogoPaddingStart;
            rect.bottom = result.getHeight() - mLogoPaddingBottom;
            rect.top = rect.bottom - scaledLogo.getHeight();
        } else {
            int marginStart = (result.getWidth() - mCardImageMaxWidth) / 2;
            startPadding = mLogoPaddingStart + marginStart;
            rect.bottom = result.getHeight() - mLogoPaddingBottom;
            rect.top = rect.bottom - scaledLogo.getHeight();
        }
        if (getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
            rect.left = startPadding;
            rect.right = startPadding + scaledLogo.getWidth();
        } else {
            rect.right = result.getWidth() - startPadding;
            rect.left = rect.right - scaledLogo.getWidth();
        }
        Paint paint = new Paint();
        paint.setAlpha(getResources().getInteger(R.integer.notif_card_ch_logo_alpha));
        canvas.drawBitmap(scaledLogo, null, rect, paint);
        return result;
    }

    private boolean isNotifiedChannel(long channelId) {
        for (int i = 0; i < NOTIFICATION_COUNT; ++i) {
            if (mNotificationChannels[i] == channelId) {
                return true;
            }
        }
        return false;
    }

    private int getAvailableNotificationId() {
        for (int i = 0; i < NOTIFICATION_COUNT; ++i) {
            if (mNotificationChannels[i] == Channel.INVALID_ID) {
                return i;
            }
        }
        return -1;
    }

    private static class NotificationHandler extends WeakHandler<NotificationService> {
        public NotificationHandler(@NonNull Looper looper, NotificationService ref) {
            super(looper, ref);
        }

        @Override
        public void handleMessage(Message msg, @NonNull NotificationService notificationService) {
            switch (msg.what) {
                case MSG_INITIALIZE_RECOMMENDER:
                    {
                        notificationService.handleInitializeRecommender();
                        break;
                    }
                case MSG_SHOW_RECOMMENDATION:
                    {
                        notificationService.handleShowRecommendation();
                        break;
                    }
                case MSG_UPDATE_RECOMMENDATION:
                    {
                        int notificationId = msg.arg1;
                        Channel channel = ((Channel) msg.obj);
                        notificationService.handleUpdateRecommendation(notificationId, channel);
                        break;
                    }
                case MSG_HIDE_RECOMMENDATION:
                    {
                        notificationService.handleHideRecommendation();
                        break;
                    }
                default:
                    {
                        super.handleMessage(msg);
                    }
            }
        }
    }
}
