/*
 * 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.content.Context;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.util.Pair;
import com.android.tv.data.api.Channel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class Recommender implements RecommendationDataManager.Listener {
    private static final String TAG = "Recommender";

    @VisibleForTesting static final String INVALID_CHANNEL_SORT_KEY = "INVALID";
    private static final long MINIMUM_RECOMMENDATION_UPDATE_PERIOD = TimeUnit.MINUTES.toMillis(5);
    private static final Comparator<Pair<Channel, Double>> mChannelScoreComparator =
            new Comparator<Pair<Channel, Double>>() {
                @Override
                public int compare(Pair<Channel, Double> lhs, Pair<Channel, Double> rhs) {
                    // Sort the scores with descending order.
                    return rhs.second.compareTo(lhs.second);
                }
            };

    private final List<EvaluatorWrapper> mEvaluators = new ArrayList<>();
    private final boolean mIncludeRecommendedOnly;
    private final Listener mListener;

    private final Map<Long, String> mChannelSortKey = new HashMap<>();
    private final RecommendationDataManager mDataManager;
    private List<Channel> mPreviousRecommendedChannels = new ArrayList<>();
    private long mLastRecommendationUpdatedTimeUtcMillis;
    private boolean mChannelRecordLoaded;

    /**
     * Create a recommender object.
     *
     * @param includeRecommendedOnly true to include only recommended results, or false.
     */
    public Recommender(Context context, Listener listener, boolean includeRecommendedOnly) {
        mListener = listener;
        mIncludeRecommendedOnly = includeRecommendedOnly;
        mDataManager = RecommendationDataManager.acquireManager(context, this);
    }

    @VisibleForTesting
    Recommender(
            Listener listener,
            boolean includeRecommendedOnly,
            RecommendationDataManager dataManager) {
        mListener = listener;
        mIncludeRecommendedOnly = includeRecommendedOnly;
        mDataManager = dataManager;
    }

    public boolean isReady() {
        return mChannelRecordLoaded;
    }

    public void release() {
        mDataManager.release(this);
    }

    public void registerEvaluator(Evaluator evaluator) {
        registerEvaluator(
                evaluator, EvaluatorWrapper.DEFAULT_BASE_SCORE, EvaluatorWrapper.DEFAULT_WEIGHT);
    }

    /**
     * Register the evaluator used in recommendation.
     *
     * <p>The range of evaluated scores by this evaluator will be between {@code baseScore} and
     * {@code baseScore} + {@code weight} (inclusive).
     *
     * @param evaluator The evaluator to register inside this recommender.
     * @param baseScore Base(Minimum) score of the score evaluated by {@code evaluator}.
     * @param weight Weight value to rearrange the score evaluated by {@code evaluator}.
     */
    public void registerEvaluator(Evaluator evaluator, double baseScore, double weight) {
        mEvaluators.add(new EvaluatorWrapper(this, evaluator, baseScore, weight));
    }

    public List<Channel> recommendChannels() {
        return recommendChannels(mDataManager.getChannelRecordCount());
    }

    /**
     * Return the channel list of recommendation up to {@code n} or the number of channels. During
     * the evaluation, this method updates the channel sort key of recommended channels.
     *
     * @param size The number of channels that might be recommended.
     * @return Top {@code size} channels recommended sorted by score in descending order. If {@code
     *     size} is bigger than the number of channels, the number of results could be less than
     *     {@code size}.
     */
    public List<Channel> recommendChannels(int size) {
        List<Pair<Channel, Double>> records = new ArrayList<>();
        Collection<ChannelRecord> channelRecordList = mDataManager.getChannelRecords();
        for (ChannelRecord cr : channelRecordList) {
            double maxScore = Evaluator.NOT_RECOMMENDED;
            for (EvaluatorWrapper evaluator : mEvaluators) {
                double score = evaluator.getScaledEvaluatorScore(cr.getChannel().getId());
                if (score > maxScore) {
                    maxScore = score;
                }
            }
            if (!mIncludeRecommendedOnly || maxScore != Evaluator.NOT_RECOMMENDED) {
                records.add(new Pair<>(cr.getChannel(), maxScore));
            }
        }
        if (size > records.size()) {
            size = records.size();
        }
        Collections.sort(records, mChannelScoreComparator);

        List<Channel> results = new ArrayList<>();

        mChannelSortKey.clear();
        String sortKeyFormat = "%0" + String.valueOf(size).length() + "d";
        for (int i = 0; i < size; ++i) {
            // Channel with smaller sort key has higher priority.
            mChannelSortKey.put(records.get(i).first.getId(), String.format(sortKeyFormat, i));
            results.add(records.get(i).first);
        }
        return results;
    }

    /**
     * Returns the {@link Channel} object for a given channel ID from the channel pool that this
     * recommendation engine has.
     *
     * @param channelId The channel ID to retrieve the {@link Channel} object for.
     * @return the {@link Channel} object for the given channel ID, {@code null} if such a channel
     *     is not found.
     */
    public Channel getChannel(long channelId) {
        ChannelRecord record = mDataManager.getChannelRecord(channelId);
        return record == null ? null : record.getChannel();
    }

    /**
     * Returns the {@link ChannelRecord} object for a given channel ID.
     *
     * @param channelId The channel ID to receive the {@link ChannelRecord} object for.
     * @return the {@link ChannelRecord} object for the given channel ID.
     */
    public ChannelRecord getChannelRecord(long channelId) {
        return mDataManager.getChannelRecord(channelId);
    }

    /**
     * Returns the sort key of a given channel Id. Sort key is determined in {@link
     * #recommendChannels()} and getChannelSortKey must be called after that.
     *
     * <p>If getChannelSortKey was called before evaluating the channels or trying to get sort key
     * of non-recommended channel, it returns {@link #INVALID_CHANNEL_SORT_KEY}.
     */
    public String getChannelSortKey(long channelId) {
        String key = mChannelSortKey.get(channelId);
        return key == null ? INVALID_CHANNEL_SORT_KEY : key;
    }

    @Override
    public void onChannelRecordLoaded() {
        mChannelRecordLoaded = true;
        mListener.onRecommenderReady();
        List<ChannelRecord> channels = new ArrayList<>(mDataManager.getChannelRecords());
        for (EvaluatorWrapper evaluator : mEvaluators) {
            evaluator.onChannelListChanged(Collections.unmodifiableList(channels));
        }
    }

    @Override
    public void onNewWatchLog(ChannelRecord channelRecord) {
        for (EvaluatorWrapper evaluator : mEvaluators) {
            evaluator.onNewWatchLog(channelRecord);
        }
        checkRecommendationChanged();
    }

    @Override
    public void onChannelRecordChanged() {
        if (mChannelRecordLoaded) {
            List<ChannelRecord> channels = new ArrayList<>(mDataManager.getChannelRecords());
            for (EvaluatorWrapper evaluator : mEvaluators) {
                evaluator.onChannelListChanged(Collections.unmodifiableList(channels));
            }
        }
        checkRecommendationChanged();
    }

    private void checkRecommendationChanged() {
        long currentTimeUtcMillis = System.currentTimeMillis();
        if (currentTimeUtcMillis - mLastRecommendationUpdatedTimeUtcMillis
                < MINIMUM_RECOMMENDATION_UPDATE_PERIOD) {
            return;
        }
        mLastRecommendationUpdatedTimeUtcMillis = currentTimeUtcMillis;
        List<Channel> recommendedChannels = recommendChannels();
        if (!recommendedChannels.equals(mPreviousRecommendedChannels)) {
            mPreviousRecommendedChannels = recommendedChannels;
            mListener.onRecommendationChanged();
        }
    }

    @VisibleForTesting
    void setLastRecommendationUpdatedTimeUtcMs(long newUpdatedTimeMs) {
        mLastRecommendationUpdatedTimeUtcMillis = newUpdatedTimeMs;
    }

    public abstract static class Evaluator {
        public static final double NOT_RECOMMENDED = -1.0;
        private Recommender mRecommender;

        protected Evaluator() {}

        protected void onChannelRecordListChanged(List<ChannelRecord> channelRecords) {}

        /**
         * This will be called when a new watch log comes into WatchedPrograms table.
         *
         * @param channelRecord The channel record corresponds to the new watch log.
         */
        protected void onNewWatchLog(ChannelRecord channelRecord) {}

        /**
         * The implementation should return the recommendation score for the given channel ID. The
         * return value should be in the range of [0.0, 1.0] or NOT_RECOMMENDED for denoting that it
         * gives up to calculate the score for the channel.
         *
         * @param channelId The channel ID which will be evaluated by this recommender.
         * @return The recommendation score
         */
        protected abstract double evaluateChannel(final long channelId);

        protected void setRecommender(Recommender recommender) {
            mRecommender = recommender;
        }

        protected Recommender getRecommender() {
            return mRecommender;
        }
    }

    private static class EvaluatorWrapper {
        private static final double DEFAULT_BASE_SCORE = 0.0;
        private static final double DEFAULT_WEIGHT = 1.0;

        private final Evaluator mEvaluator;
        // The minimum score of the Recommender unless it gives up to provide the score.
        private final double mBaseScore;
        // The weight of the recommender. The return-value of getScore() will be multiplied by
        // this value.
        private final double mWeight;

        public EvaluatorWrapper(
                Recommender recommender, Evaluator evaluator, double baseScore, double weight) {
            mEvaluator = evaluator;
            evaluator.setRecommender(recommender);
            mBaseScore = baseScore;
            mWeight = weight;
        }

        /**
         * This returns the scaled score for the given channel ID based on the returned value of
         * evaluateChannel().
         *
         * @param channelId The channel ID which will be evaluated by the recommender.
         * @return Returns the scaled score (mBaseScore + score * mWeight) when evaluateChannel() is
         *     in the range of [0.0, 1.0]. If evaluateChannel() returns NOT_RECOMMENDED or any
         *     negative numbers, it returns NOT_RECOMMENDED. If calculateScore() returns more than
         *     1.0, it returns (mBaseScore + mWeight).
         */
        private double getScaledEvaluatorScore(long channelId) {
            double score = mEvaluator.evaluateChannel(channelId);
            if (score < 0.0) {
                if (score != Evaluator.NOT_RECOMMENDED) {
                    Log.w(
                            TAG,
                            "Unexpected score (" + score + ") from the recommender" + mEvaluator);
                }
                // If the recommender gives up to calculate the score, return 0.0
                return Evaluator.NOT_RECOMMENDED;
            } else if (score > 1.0) {
                Log.w(TAG, "Unexpected score (" + score + ") from the recommender" + mEvaluator);
                score = 1.0;
            }
            return mBaseScore + score * mWeight;
        }

        public void onNewWatchLog(ChannelRecord channelRecord) {
            mEvaluator.onNewWatchLog(channelRecord);
        }

        public void onChannelListChanged(List<ChannelRecord> channelRecords) {
            mEvaluator.onChannelRecordListChanged(channelRecords);
        }
    }

    public interface Listener {
        /** Called after channel record map is loaded. */
        void onRecommenderReady();

        /** Called when the recommendation changes. */
        void onRecommendationChanged();
    }
}
