/*
 * Copyright (C) 2016 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.tuner.source;

import android.content.Context;

import com.android.tv.common.AutoCloseableUtils;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.tuner.TunerHal;
import com.android.tv.tuner.data.TunerChannel;
import com.android.tv.tuner.tvinput.EventDetector;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Manages {@link TunerTsStreamer} for playback and recording.
 * The class hides handling of {@link TunerHal} from other classes.
 * This class is used by {@link TsDataSourceManager}. Don't use this class directly.
 */
class TunerTsStreamerManager {
    // The lock will protect mStreamerFinder, mSourceToStreamerMap and some part of TsStreamCreator
    // to support timely {@link TunerTsStreamer} cancellation due to a new tune request from
    // the same session.
    private final Object mCancelLock = new Object();
    private final StreamerFinder mStreamerFinder = new StreamerFinder();
    private final Map<Integer, TsStreamerCreator> mCreators = new HashMap<>();
    private final Map<TsDataSource, TunerTsStreamer> mSourceToStreamerMap = new HashMap<>();
    private final TunerHalManager mTunerHalManager = new TunerHalManager();
    private static TunerTsStreamerManager sInstance;

    /**
     * Returns the singleton instance for the class
     * @return TunerTsStreamerManager
     */
    static synchronized TunerTsStreamerManager getInstance() {
        if (sInstance == null) {
            sInstance = new TunerTsStreamerManager();
        }
        return sInstance;
    }

    private TunerTsStreamerManager() { }

    synchronized TsDataSource createDataSource(
            Context context, TunerChannel channel, EventDetector.EventListener listener,
            int sessionId, boolean reuse) {
        TsStreamerCreator creator;
        synchronized (mCancelLock) {
            if (mStreamerFinder.containsLocked(channel)) {
                mStreamerFinder.appendSessionLocked(channel, sessionId);
                TunerTsStreamer streamer =  mStreamerFinder.getStreamerLocked(channel);
                TsDataSource source = streamer.createDataSource();
                mSourceToStreamerMap.put(source, streamer);
                return source;
            }
            creator = new TsStreamerCreator(context, channel, listener);
            mCreators.put(sessionId, creator);
        }
        TunerTsStreamer streamer = creator.create(sessionId, reuse);
        synchronized (mCancelLock) {
            mCreators.remove(sessionId);
            if (streamer == null) {
                return null;
            }
            if (!creator.isCancelledLocked()) {
                mStreamerFinder.putLocked(channel, sessionId, streamer);
                TsDataSource source = streamer.createDataSource();
                mSourceToStreamerMap.put(source, streamer);
                return source;
            }
        }
        // Created streamer was cancelled by a new tune request.
        streamer.stopStream();
        TunerHal hal = streamer.getTunerHal();
        hal.setHasPendingTune(false);
        mTunerHalManager.releaseTunerHal(hal, sessionId, reuse);
        return null;
    }

    synchronized void releaseDataSource(TsDataSource source, int sessionId,
            boolean reuse) {
        TunerTsStreamer streamer;
        synchronized (mCancelLock) {
            streamer = mSourceToStreamerMap.get(source);
            mSourceToStreamerMap.remove(source);
            if (streamer == null) {
                return;
            }
            TunerChannel channel = streamer.getChannel();
            SoftPreconditions.checkState(channel != null);
            mStreamerFinder.removeSessionLocked(channel, sessionId);
            if (mStreamerFinder.containsLocked(channel)) {
                return;
            }
        }
        streamer.stopStream();
        TunerHal hal = streamer.getTunerHal();
        hal.setHasPendingTune(false);
        mTunerHalManager.releaseTunerHal(hal, sessionId, reuse);
    }

    void setHasPendingTune(int sessionId) {
        synchronized (mCancelLock) {
           if (mCreators.containsKey(sessionId)) {
               mCreators.get(sessionId).cancelLocked();
           }
        }
    }

    synchronized void release(int sessionId) {
        mTunerHalManager.releaseCachedHal(sessionId);
    }

    private class StreamerFinder {
        private final Map<TunerChannel, Set<Integer>> mSessions = new HashMap<>();
        private final Map<TunerChannel, TunerTsStreamer> mStreamers = new HashMap<>();

        // @GuardedBy("mCancelLock")
        private void putLocked(TunerChannel channel, int sessionId, TunerTsStreamer streamer) {
            Set<Integer> sessions = new HashSet<>();
            sessions.add(sessionId);
            mSessions.put(channel, sessions);
            mStreamers.put(channel, streamer);
        }

        // @GuardedBy("mCancelLock")
        private void appendSessionLocked(TunerChannel channel, int sessionId) {
            if (mSessions.containsKey(channel)) {
                mSessions.get(channel).add(sessionId);
            }
        }

        // @GuardedBy("mCancelLock")
        private void removeSessionLocked(TunerChannel channel, int sessionId) {
            Set<Integer> sessions = mSessions.get(channel);
            sessions.remove(sessionId);
            if (sessions.size() == 0) {
                mSessions.remove(channel);
                mStreamers.remove(channel);
            }
        }

        // @GuardedBy("mCancelLock")
        private boolean containsLocked(TunerChannel channel) {
            return mSessions.containsKey(channel);
        }

        // @GuardedBy("mCancelLock")
        private TunerTsStreamer getStreamerLocked(TunerChannel channel) {
            return mStreamers.containsKey(channel) ? mStreamers.get(channel) : null;
        }
    }

    /**
     * {@link TunerTsStreamer} creation can be cancelled by a new tune request for the same
     * session. The class supports the cancellation in creating new {@link TunerTsStreamer}.
     */
    private class TsStreamerCreator {
        private final Context mContext;
        private final TunerChannel mChannel;
        private final EventDetector.EventListener mEventListener;
        // mCancelled will be {@code true} if a new tune request for the same session
        // cancels create().
        private boolean mCancelled;
        private TunerHal mTunerHal;

        private TsStreamerCreator(Context context, TunerChannel channel,
                EventDetector.EventListener listener) {
            mContext = context;
            mChannel = channel;
            mEventListener = listener;
        }

        private TunerTsStreamer create(int sessionId, boolean reuse) {
            TunerHal hal = mTunerHalManager.getOrCreateTunerHal(mContext, sessionId);
            if (hal == null) {
                return null;
            }
            boolean canceled = false;
            synchronized (mCancelLock) {
                if (!mCancelled) {
                    mTunerHal = hal;
                } else {
                    canceled = true;
                }
            }
            if (!canceled) {
                TunerTsStreamer tsStreamer = new TunerTsStreamer(hal, mEventListener, mContext);
                if (tsStreamer.startStream(mChannel)) {
                    return tsStreamer;
                }
                synchronized (mCancelLock) {
                    mTunerHal = null;
                }
            }
            hal.setHasPendingTune(false);
            // Since TunerTsStreamer is not properly created, closes TunerHal.
            // And do not re-use TunerHal when it is not cancelled.
            mTunerHalManager.releaseTunerHal(hal, sessionId, mCancelled && reuse);
            return null;
        }

        // @GuardedBy("mCancelLock")
        private void cancelLocked() {
                if (mCancelled) {
                    return;
                }
                mCancelled = true;
                if (mTunerHal != null) {
                    mTunerHal.setHasPendingTune(true);
                }
        }

        // @GuardedBy("mCancelLock")
        private boolean isCancelledLocked() {
                return mCancelled;
        }
    }

    /**
     * Supports sharing {@link TunerHal} among multiple sessions.
     * The class also supports session affinity for {@link TunerHal} allocation.
     */
    private class TunerHalManager {
        private final Map<Integer, TunerHal> mTunerHals = new HashMap<>();

        private TunerHal getOrCreateTunerHal(Context context, int sessionId) {
            // Handles session affinity.
            TunerHal hal = mTunerHals.get(sessionId);
            if (hal != null) {
                mTunerHals.remove(sessionId);
                return hal;
            }
            // Finds a TunerHal which is cached for other sessions.
            Iterator it = mTunerHals.keySet().iterator();
            if (it.hasNext()) {
                Integer key = (Integer) it.next();
                hal = mTunerHals.get(key);
                mTunerHals.remove(key);
                return hal;
            }
            return TunerHal.createInstance(context);
        }

        private void releaseTunerHal(TunerHal hal, int sessionId, boolean reuse) {
            if (!reuse) {
                AutoCloseableUtils.closeQuietly(hal);
                return;
            }
            TunerHal cachedHal = mTunerHals.get(sessionId);
            if (cachedHal != hal) {
                mTunerHals.put(sessionId, hal);
            }
            if (cachedHal != null && cachedHal != hal) {
                AutoCloseableUtils.closeQuietly(cachedHal);
            }
        }

        private void releaseCachedHal(int sessionId) {
            TunerHal hal = mTunerHals.get(sessionId);
            if (hal != null) {
                mTunerHals.remove(sessionId);
            }
            if (hal != null) {
                AutoCloseableUtils.closeQuietly(hal);
            }
        }
    }
}