/*
 * Copyright (C) 2011 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.speech.tts;

import android.speech.tts.TextToSpeechService.AudioOutputParams;
import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
import android.media.AudioTrack;
import android.util.Log;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Manages the playback of a list of byte arrays representing audio data that are queued by the
 * engine to an audio track.
 */
final class SynthesisPlaybackQueueItem extends PlaybackQueueItem
        implements AudioTrack.OnPlaybackPositionUpdateListener {
    private static final String TAG = "TTS.SynthQueueItem";
    private static final boolean DBG = false;

    /**
     * Maximum length of audio we leave unconsumed by the audio track.
     * Calls to {@link #put(byte[])} will block until we have less than
     * this amount of audio left to play back.
     */
    private static final long MAX_UNCONSUMED_AUDIO_MS = 500;

    /**
     * Guards accesses to mDataBufferList and mUnconsumedBytes.
     */
    private final Lock mListLock = new ReentrantLock();
    private final Condition mReadReady = mListLock.newCondition();
    private final Condition mNotFull = mListLock.newCondition();

    // Guarded by mListLock.
    private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>();
    // Guarded by mListLock.
    private int mUnconsumedBytes;

    /*
     * While mStopped and mIsError can be written from any thread, mDone is written
     * only from the synthesis thread. All three variables are read from the
     * audio playback thread.
     */
    private volatile boolean mStopped;
    private volatile boolean mDone;
    private volatile int mStatusCode;

    private final BlockingAudioTrack mAudioTrack;
    private final AbstractEventLogger mLogger;

    // Stores a queue of markers. When the marker in front is reached the client is informed and we
    // wait for the next one.
    private ConcurrentLinkedQueue<ProgressMarker> markerList = new ConcurrentLinkedQueue<>();

    SynthesisPlaybackQueueItem(AudioOutputParams audioParams, int sampleRate,
            int audioFormat, int channelCount, UtteranceProgressDispatcher dispatcher,
            Object callerIdentity, AbstractEventLogger logger) {
        super(dispatcher, callerIdentity);

        mUnconsumedBytes = 0;

        mStopped = false;
        mDone = false;
        mStatusCode = TextToSpeech.SUCCESS;

        mAudioTrack = new BlockingAudioTrack(audioParams, sampleRate, audioFormat, channelCount);
        mLogger = logger;
    }


    @Override
    public void run() {
        final UtteranceProgressDispatcher dispatcher = getDispatcher();
        dispatcher.dispatchOnStart();

        if (!mAudioTrack.init()) {
            dispatcher.dispatchOnError(TextToSpeech.ERROR_OUTPUT);
            return;
        }

        mAudioTrack.setPlaybackPositionUpdateListener(this);
        // Ensure we set the first marker if there is one.
        updateMarker();

        try {
            byte[] buffer = null;

            // take() will block until:
            //
            // (a) there is a buffer available to tread. In which case
            // a non null value is returned.
            // OR (b) stop() is called in which case it will return null.
            // OR (c) done() is called in which case it will return null.
            while ((buffer = take()) != null) {
                mAudioTrack.write(buffer);
                mLogger.onAudioDataWritten();
            }

        } catch (InterruptedException ie) {
            if (DBG) Log.d(TAG, "Interrupted waiting for buffers, cleaning up.");
        }

        mAudioTrack.waitAndRelease();

        if (mStatusCode == TextToSpeech.SUCCESS) {
            dispatcher.dispatchOnSuccess();
        } else if(mStatusCode == TextToSpeech.STOPPED) {
            dispatcher.dispatchOnStop();
        } else {
            dispatcher.dispatchOnError(mStatusCode);
        }

        mLogger.onCompleted(mStatusCode);
    }

    @Override
    void stop(int statusCode) {
        try {
            mListLock.lock();

            // Update our internal state.
            mStopped = true;
            mStatusCode = statusCode;

            // Wake up the audio playback thread if it was waiting on take().
            // take() will return null since mStopped was true, and will then
            // break out of the data write loop.
            mReadReady.signal();

            // Wake up the synthesis thread if it was waiting on put(). Its
            // buffers will no longer be copied since mStopped is true. The
            // PlaybackSynthesisCallback that this synthesis corresponds to
            // would also have been stopped, and so all calls to
            // Callback.onDataAvailable( ) will return errors too.
            mNotFull.signal();
        } finally {
            mListLock.unlock();
        }

        // Stop the underlying audio track. This will stop sending
        // data to the mixer and discard any pending buffers that the
        // track holds.
        mAudioTrack.stop();
    }

    void done() {
        try {
            mListLock.lock();

            // Update state.
            mDone = true;

            // Unblocks the audio playback thread if it was waiting on take()
            // after having consumed all available buffers. It will then return
            // null and leave the write loop.
            mReadReady.signal();

            // Just so that engines that try to queue buffers after
            // calling done() don't block the synthesis thread forever. Ideally
            // this should be called from the same thread as put() is, and hence
            // this call should be pointless.
            mNotFull.signal();
        } finally {
            mListLock.unlock();
        }
    }

    /** Convenience class for passing around TTS markers. */
    private class ProgressMarker {
        // The index in frames of this marker.
        public final int frames;
        // The start index in the text of the utterance.
        public final int start;
        // The end index (exclusive) in the text of the utterance.
        public final int end;

        public ProgressMarker(int frames, int start, int end) {
            this.frames = frames;
            this.start = start;
            this.end = end;
        }
    }

    /** Set a callback for the first marker in the queue. */
    void updateMarker() {
        ProgressMarker marker = markerList.peek();
        if (marker != null) {
            // Zero is used to disable the marker. The documentation recommends to use a non-zero
            // position near zero such as 1.
            int markerInFrames = marker.frames == 0 ? 1 : marker.frames;
            mAudioTrack.setNotificationMarkerPosition(markerInFrames);
        }
    }

    /** Informs us that at markerInFrames, the range between start and end is about to be spoken. */
    void rangeStart(int markerInFrames, int start, int end) {
        markerList.add(new ProgressMarker(markerInFrames, start, end));
        updateMarker();
    }

    @Override
    public void onMarkerReached(AudioTrack track) {
        ProgressMarker marker = markerList.poll();
        if (marker == null) {
            Log.e(TAG, "onMarkerReached reached called but no marker in queue");
            return;
        }
        // Inform the client.
        getDispatcher().dispatchOnRangeStart(marker.start, marker.end, marker.frames);
        // Listen for the next marker.
        // It's ok if this marker is in the past, in that case onMarkerReached will be called again.
        updateMarker();
    }

    @Override
    public void onPeriodicNotification(AudioTrack track) {}

    void put(byte[] buffer) throws InterruptedException {
        try {
            mListLock.lock();
            long unconsumedAudioMs = 0;

            while ((unconsumedAudioMs = mAudioTrack.getAudioLengthMs(mUnconsumedBytes)) >
                    MAX_UNCONSUMED_AUDIO_MS && !mStopped) {
                mNotFull.await();
            }

            // Don't bother queueing the buffer if we've stopped. The playback thread
            // would have woken up when stop() is called (if it was blocked) and will
            // proceed to leave the write loop since take() will return null when
            // stopped.
            if (mStopped) {
                return;
            }

            mDataBufferList.add(new ListEntry(buffer));
            mUnconsumedBytes += buffer.length;
            mReadReady.signal();
        } finally {
            mListLock.unlock();
        }
    }

    private byte[] take() throws InterruptedException {
        try {
            mListLock.lock();

            // Block if there are no available buffers, and stop() has not
            // been called and done() has not been called.
            while (mDataBufferList.size() == 0 && !mStopped && !mDone) {
                mReadReady.await();
            }

            // If stopped, return null so that we can exit the playback loop
            // as soon as possible.
            if (mStopped) {
                return null;
            }

            // Remove the first entry from the queue.
            ListEntry entry = mDataBufferList.poll();

            // This is the normal playback loop exit case, when done() was
            // called. (mDone will be true at this point).
            if (entry == null) {
                return null;
            }

            mUnconsumedBytes -= entry.mBytes.length;
            // Unblock the waiting writer. We use signal() and not signalAll()
            // because there will only be one thread waiting on this (the
            // Synthesis thread).
            mNotFull.signal();

            return entry.mBytes;
        } finally {
            mListLock.unlock();
        }
    }

    static final class ListEntry {
        final byte[] mBytes;

        ListEntry(byte[] bytes) {
            mBytes = bytes;
        }
    }
}
