/*
 * 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.tuner.exoplayer.ac3;

import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;

import com.google.android.exoplayer.CodecCounters;
import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.MediaClock;
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
import com.google.android.exoplayer.MediaFormat;
import com.google.android.exoplayer.MediaFormatHolder;
import com.google.android.exoplayer.MediaFormatUtil;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.SampleSource;
import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.audio.AudioTrack;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.MimeTypes;
import com.android.tv.tuner.tvinput.TunerDebug;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;

/**
 * Decodes and renders AC3 audio.
 */
public class Ac3PassthroughTrackRenderer extends TrackRenderer implements MediaClock {
    public static final int MSG_SET_VOLUME = 10000;
    public static final int MSG_SET_AUDIO_TRACK = MSG_SET_VOLUME + 1;
    public static final int MSG_SET_PLAYBACK_SPEED = MSG_SET_VOLUME + 2;

    // ATSC/53 allows sample rate to be only 48Khz.
    // One AC3 sample has 1536 frames, and its duration is 32ms.
    public static final long AC3_SAMPLE_DURATION_US = 32000;

    private static final String TAG = "Ac3PassthroughTrackRenderer";
    private static final boolean DEBUG = false;

    /**
     * Interface definition for a callback to be notified of
     * {@link com.google.android.exoplayer.audio.AudioTrack} error.
     */
    public interface EventListener {
        void onAudioTrackInitializationError(AudioTrack.InitializationException e);
        void onAudioTrackWriteError(AudioTrack.WriteException e);
    }

    private static final int DEFAULT_INPUT_BUFFER_SIZE = 16384 * 2;
    private static final int DEFAULT_OUTPUT_BUFFER_SIZE = 1024*1024;
    private static final int MONITOR_DURATION_MS = 1000;
    private static final int AC3_HEADER_BITRATE_OFFSET = 4;

    // Keep this as static in order to prevent new framework AudioTrack creation
    // while old AudioTrack is being released.
    private static final AudioTrackWrapper AUDIO_TRACK = new AudioTrackWrapper();
    private static final long KEEP_ALIVE_AFTER_EOS_DURATION_MS = 3000;

    // Ignore AudioTrack backward movement if duration of movement is below the threshold.
    private static final long BACKWARD_AUDIO_TRACK_MOVE_THRESHOLD_US = 3000;

    // AudioTrack position cannot go ahead beyond this limit.
    private static final long CURRENT_POSITION_FROM_PTS_LIMIT_US = 1000000;

    // Since MediaCodec processing and AudioTrack playing add delay,
    // PTS interpolated time should be delayed reasonably when AudioTrack is not used.
    private static final long ESTIMATED_TRACK_RENDERING_DELAY_US = 500000;

    private final CodecCounters mCodecCounters;
    private final SampleSource.SampleSourceReader mSource;
    private final SampleHolder mSampleHolder;
    private final MediaFormatHolder mFormatHolder;
    private final EventListener mEventListener;
    private final Handler mEventHandler;
    private final AudioTrackMonitor mMonitor;
    private final AudioClock mAudioClock;

    private MediaFormat mFormat;
    private final ByteBuffer mOutputBuffer;
    private boolean mOutputReady;
    private int mTrackIndex;
    private boolean mSourceStateReady;
    private boolean mInputStreamEnded;
    private boolean mOutputStreamEnded;
    private long mEndOfStreamMs;
    private long mCurrentPositionUs;
    private int mPresentationCount;
    private long mPresentationTimeUs;
    private long mInterpolatedTimeUs;
    private long mPreviousPositionUs;
    private boolean mIsStopped;
    private ArrayList<Integer> mTracksIndex;

    public Ac3PassthroughTrackRenderer(SampleSource source, Handler eventHandler,
            EventListener listener) {
        mSource = source.register();
        mEventHandler = eventHandler;
        mEventListener = listener;
        mTrackIndex = -1;
        mSampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DIRECT);
        mSampleHolder.ensureSpaceForWrite(DEFAULT_INPUT_BUFFER_SIZE);
        mOutputBuffer = ByteBuffer.allocate(DEFAULT_OUTPUT_BUFFER_SIZE);
        mFormatHolder = new MediaFormatHolder();
        AUDIO_TRACK.restart();
        mCodecCounters = new CodecCounters();
        mMonitor = new AudioTrackMonitor();
        mAudioClock = new AudioClock();
        mTracksIndex = new ArrayList<>();
    }

    @Override
    protected MediaClock getMediaClock() {
        return this;
    }

    private static boolean handlesMimeType(String mimeType) {
        return mimeType.equals(MimeTypes.AUDIO_AC3) || mimeType.equals(MimeTypes.AUDIO_E_AC3);
    }

    @Override
    protected boolean doPrepare(long positionUs) throws ExoPlaybackException {
        boolean sourcePrepared = mSource.prepare(positionUs);
        if (!sourcePrepared) {
            return false;
        }
        for (int i = 0; i < mSource.getTrackCount(); i++) {
            if (handlesMimeType(mSource.getFormat(i).mimeType)) {
                if (mTrackIndex < 0) {
                    mTrackIndex = i;
                }
                mTracksIndex.add(i);
            }
        }

        // TODO: Check this case. Source does not have the proper mime type.
        return true;
    }

    @Override
    protected int getTrackCount() {
        return mTracksIndex.size();
    }

    @Override
    protected MediaFormat getFormat(int track) {
        Assertions.checkArgument(track >= 0 && track < mTracksIndex.size());
        return mSource.getFormat(mTracksIndex.get(track));
    }

    @Override
    protected void onEnabled(int track, long positionUs, boolean joining) {
        Assertions.checkArgument(track >= 0 && track < mTracksIndex.size());
        mTrackIndex = mTracksIndex.get(track);
        mSource.enable(mTrackIndex, positionUs);
        seekToInternal(positionUs);
    }

    @Override
    protected void onDisabled() {
        AUDIO_TRACK.resetSessionId();
        clearDecodeState();
        mFormat = null;
        mSource.disable(mTrackIndex);
    }

    @Override
    protected void onReleased() {
        AUDIO_TRACK.release();
        mSource.release();
    }

    @Override
    protected boolean isEnded() {
        return mOutputStreamEnded && AUDIO_TRACK.isEnded();
    }

    @Override
    protected boolean isReady() {
        return AUDIO_TRACK.isReady() || (mFormat != null && (mSourceStateReady || mOutputReady));
    }

    private void seekToInternal(long positionUs) {
        mMonitor.reset(MONITOR_DURATION_MS);
        mSourceStateReady = false;
        mInputStreamEnded = false;
        mOutputStreamEnded = false;
        mPresentationTimeUs = positionUs;
        mPresentationCount = 0;
        mPreviousPositionUs = 0;
        mCurrentPositionUs = Long.MIN_VALUE;
        mInterpolatedTimeUs = Long.MIN_VALUE;
        mAudioClock.setPositionUs(positionUs);
    }

    @Override
    protected void seekTo(long positionUs) {
        mSource.seekToUs(positionUs);
        AUDIO_TRACK.reset();
        // resetSessionId() will create a new framework AudioTrack instead of reusing old one.
        AUDIO_TRACK.resetSessionId();
        seekToInternal(positionUs);
    }

    @Override
    protected void onStarted() {
        AUDIO_TRACK.play();
        mAudioClock.start();
        mIsStopped = false;
    }

    @Override
    protected void onStopped() {
        AUDIO_TRACK.pause();
        mAudioClock.stop();
        mIsStopped = true;
    }

    @Override
    protected void maybeThrowError() throws ExoPlaybackException {
        try {
            mSource.maybeThrowError();
        } catch (IOException e) {
            throw new ExoPlaybackException(e);
        }
    }

    @Override
    protected void doSomeWork(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
        mMonitor.maybeLog();
        try {
            if (mEndOfStreamMs != 0) {
                // Ensure playback stops, after EoS was notified.
                // Sometimes MediaCodecTrackRenderer does not fetch EoS timely
                // after EoS was notified here long before.
                long diff = SystemClock.elapsedRealtime() - mEndOfStreamMs;
                if (diff >= KEEP_ALIVE_AFTER_EOS_DURATION_MS && !mIsStopped) {
                    throw new ExoPlaybackException("Much time has elapsed after EoS");
                }
            }
            boolean continueBuffering = mSource.continueBuffering(mTrackIndex, positionUs);
            if (mSourceStateReady != continueBuffering) {
                mSourceStateReady = continueBuffering;
                if (DEBUG) {
                    Log.d(TAG, "mSourceStateReady: " + String.valueOf(mSourceStateReady));
                }
            }
            long discontinuity = mSource.readDiscontinuity(mTrackIndex);
            if (discontinuity != SampleSource.NO_DISCONTINUITY) {
                AUDIO_TRACK.handleDiscontinuity();
                mPresentationTimeUs = discontinuity;
                mPresentationCount = 0;
                clearDecodeState();
                return;
            }
            if (mFormat == null) {
                readFormat();
                return;
            }

            // Process only one sample at a time for doSomeWork()
            if (processOutput()) {
                if (!mOutputReady) {
                    while (feedInputBuffer()) {
                        if (mOutputReady) break;
                    }
                }
            }
            mCodecCounters.ensureUpdated();
        } catch (IOException e) {
            throw new ExoPlaybackException(e);
        }
    }

    private void ensureAudioTrackInitialized() {
        if (!AUDIO_TRACK.isInitialized()) {
            try {
                if (DEBUG) {
                    Log.d(TAG, "AudioTrack initialized");
                }
                AUDIO_TRACK.initialize();
            } catch (AudioTrack.InitializationException e) {
                Log.e(TAG, "Error on AudioTrack initialization", e);
                notifyAudioTrackInitializationError(e);

                // Do not throw exception here but just disabling audioTrack to keep playing
                // video without audio.
                AUDIO_TRACK.setStatus(false);
            }
            if (getState() == TrackRenderer.STATE_STARTED) {
                if (DEBUG) {
                    Log.d(TAG, "AudioTrack played");
                }
                AUDIO_TRACK.play();
            }
        }
    }

    private void clearDecodeState() {
        mOutputReady = false;
        AUDIO_TRACK.reset();
    }

    private void readFormat() throws IOException, ExoPlaybackException {
        int result = mSource.readData(mTrackIndex, mCurrentPositionUs,
                mFormatHolder, mSampleHolder);
        if (result == SampleSource.FORMAT_READ) {
            onInputFormatChanged(mFormatHolder);
        }
    }

    private void onInputFormatChanged(MediaFormatHolder formatHolder)
            throws ExoPlaybackException {
        mFormat = formatHolder.format;
        if (DEBUG) {
            Log.d(TAG, "AudioTrack was configured to FORMAT: " + mFormat.toString());
        }
        clearDecodeState();
        AUDIO_TRACK.reconfigure(mFormat.getFrameworkMediaFormatV16());
    }

    private boolean feedInputBuffer() throws IOException, ExoPlaybackException {
        if (mInputStreamEnded) {
            return false;
        }

        mSampleHolder.data.clear();
        mSampleHolder.size = 0;
        int result = mSource.readData(mTrackIndex, mPresentationTimeUs, mFormatHolder,
                mSampleHolder);
        switch (result) {
            case SampleSource.NOTHING_READ: {
                return false;
            }
            case SampleSource.FORMAT_READ: {
                Log.i(TAG, "Format was read again");
                onInputFormatChanged(mFormatHolder);
                return true;
            }
            case SampleSource.END_OF_STREAM: {
                Log.i(TAG, "End of stream from SampleSource");
                mInputStreamEnded = true;
                return false;
            }
            default: {
                mSampleHolder.data.flip();
                decodeDone(mSampleHolder.data, mSampleHolder.timeUs);
                return true;
            }
        }
    }

    private boolean processOutput() throws ExoPlaybackException {
        if (mOutputStreamEnded) {
            return false;
        }
        if (!mOutputReady) {
            if (mInputStreamEnded) {
                mOutputStreamEnded = true;
                mEndOfStreamMs = SystemClock.elapsedRealtime();
                return false;
            }
            return true;
        }

        ensureAudioTrackInitialized();
        int handleBufferResult;
        try {
            // To reduce discontinuity, interpolate presentation time.
            mInterpolatedTimeUs = mPresentationTimeUs
                    + mPresentationCount * AC3_SAMPLE_DURATION_US;
            handleBufferResult = AUDIO_TRACK.handleBuffer(mOutputBuffer,
                    0, mOutputBuffer.limit(), mInterpolatedTimeUs);
        } catch (AudioTrack.WriteException e) {
            notifyAudioTrackWriteError(e);
            throw new ExoPlaybackException(e);
        }

        if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) {
            Log.i(TAG, "Play discontinuity happened");
            mCurrentPositionUs = Long.MIN_VALUE;
        }
        if ((handleBufferResult & AudioTrack.RESULT_BUFFER_CONSUMED) != 0) {
            mCodecCounters.renderedOutputBufferCount++;
            mOutputReady = false;
            return true;
        }
        return false;
    }

    @Override
    protected long getDurationUs() {
        return mSource.getFormat(mTrackIndex).durationUs;
    }

    @Override
    protected long getBufferedPositionUs() {
        long pos = mSource.getBufferedPositionUs();
        return pos == UNKNOWN_TIME_US || pos == END_OF_TRACK_US
                ? pos : Math.max(pos, getPositionUs());
    }

    @Override
    public long getPositionUs() {
        if (!AUDIO_TRACK.isInitialized()) {
            return mAudioClock.getPositionUs();
        } else if (!AUDIO_TRACK.isEnabled()) {
            if (mInterpolatedTimeUs > 0) {
                return mInterpolatedTimeUs - ESTIMATED_TRACK_RENDERING_DELAY_US;
            }
            return mPresentationTimeUs;
        }
        long audioTrackCurrentPositionUs = AUDIO_TRACK.getCurrentPositionUs(isEnded());
        if (audioTrackCurrentPositionUs == AudioTrack.CURRENT_POSITION_NOT_SET) {
            mPreviousPositionUs = 0L;
            if (DEBUG) {
                long oldPositionUs = Math.max(mCurrentPositionUs, 0);
                long currentPositionUs = Math.max(mPresentationTimeUs, mCurrentPositionUs);
                Log.d(TAG, "Audio position is not set, diff in us: "
                        + String.valueOf(currentPositionUs - oldPositionUs));
            }
            mCurrentPositionUs = Math.max(mPresentationTimeUs, mCurrentPositionUs);
        } else {
            if (mPreviousPositionUs
                    > audioTrackCurrentPositionUs + BACKWARD_AUDIO_TRACK_MOVE_THRESHOLD_US) {
                Log.e(TAG, "audio_position BACK JUMP: "
                        + (mPreviousPositionUs - audioTrackCurrentPositionUs));
                mCurrentPositionUs = audioTrackCurrentPositionUs;
            } else {
                mCurrentPositionUs = Math.max(mCurrentPositionUs, audioTrackCurrentPositionUs);
            }
            mPreviousPositionUs = audioTrackCurrentPositionUs;
        }
        long upperBound = mPresentationTimeUs + CURRENT_POSITION_FROM_PTS_LIMIT_US;
        if (mCurrentPositionUs > upperBound) {
            mCurrentPositionUs = upperBound;
        }
        return mCurrentPositionUs;
    }

    private void decodeDone(ByteBuffer outputBuffer, long presentationTimeUs) {
        if (outputBuffer == null || mOutputBuffer == null) {
            return;
        }
        if (presentationTimeUs < 0) {
            Log.e(TAG, "decodeDone - invalid presentationTimeUs");
            return;
        }

        if (TunerDebug.ENABLED) {
            TunerDebug.setAudioPtsUs(presentationTimeUs);
        }

        mOutputBuffer.clear();
        Assertions.checkState(mOutputBuffer.remaining() >= outputBuffer.limit());

        mOutputBuffer.put(outputBuffer);
        mMonitor.addPts(presentationTimeUs, mOutputBuffer.position(),
                mOutputBuffer.get(AC3_HEADER_BITRATE_OFFSET));
        if (presentationTimeUs == mPresentationTimeUs) {
            mPresentationCount++;
        } else {
            mPresentationCount = 0;
            mPresentationTimeUs = presentationTimeUs;
        }
        mOutputBuffer.flip();
        mOutputReady = true;
    }

    private void notifyAudioTrackInitializationError(final AudioTrack.InitializationException e) {
        if (mEventHandler == null || mEventListener == null) {
            return;
        }
        mEventHandler.post(new Runnable() {
            @Override
            public void run() {
                mEventListener.onAudioTrackInitializationError(e);
            }
        });
    }

    private void notifyAudioTrackWriteError(final AudioTrack.WriteException e) {
        if (mEventHandler == null || mEventListener == null) {
            return;
        }
        mEventHandler.post(new Runnable() {
            @Override
            public void run() {
                mEventListener.onAudioTrackWriteError(e);
            }
        });
    }

    @Override
    public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
        switch (messageType) {
            case MSG_SET_VOLUME:
                AUDIO_TRACK.setVolume((Float) message);
                break;
            case MSG_SET_AUDIO_TRACK:
                boolean enabled = (Integer) message == 1;
                if (enabled == AUDIO_TRACK.isEnabled()) {
                    return;
                }
                if (!enabled) {
                    // mAudioClock can be different from getPositionUs. In order to sync them,
                    // we set mAudioClock.
                    mAudioClock.setPositionUs(getPositionUs());
                }
                AUDIO_TRACK.setStatus(enabled);
                if (enabled) {
                    // When AUDIO_TRACK is enabled, we need to clear AUDIO_TRACK and seek to
                    // the current position. If not, AUDIO_TRACK has the obsolete data.
                    seekTo(mAudioClock.getPositionUs());
                }
                break;
            case MSG_SET_PLAYBACK_SPEED:
                mAudioClock.setPlaybackSpeed((Float) message);
                break;
            default:
                super.handleMessage(messageType, message);
        }
    }
}
