/**
 * Copyright 2015 CANAL+ Group
 *
 * 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.
 */
import SharedReference from "../../../utils/reference";
import TaskCanceller from "../../../utils/task_canceller";
/**
 * Create PlaybackObserver for the `Stream` part of the code.
 * @param {Object} srcPlaybackObserver - Base `PlaybackObserver` from which we
 * will derive information.
 * @param {Object} context - Various information linked to the current content
 * being played.
 * @param {Object} fnCancelSignal - Abort the created PlaybackObserver.
 * @returns {Object}
 */
export default function createStreamPlaybackObserver(srcPlaybackObserver, _a, fnCancelSignal) {
    var autoPlay = _a.autoPlay, initialPlayPerformed = _a.initialPlayPerformed, initialSeekPerformed = _a.initialSeekPerformed, manifest = _a.manifest, speed = _a.speed, startTime = _a.startTime;
    return srcPlaybackObserver.deriveReadOnlyObserver(function transform(observationRef, parentObserverCancelSignal) {
        var canceller = new TaskCanceller();
        canceller.linkToSignal(parentObserverCancelSignal);
        canceller.linkToSignal(fnCancelSignal);
        var newRef = new SharedReference(constructStreamPlaybackObservation(), canceller.signal);
        speed.onUpdate(emitStreamPlaybackObservation, {
            clearSignal: canceller.signal,
            emitCurrentValue: false,
        });
        observationRef.onUpdate(emitStreamPlaybackObservation, {
            clearSignal: canceller.signal,
            emitCurrentValue: false,
        });
        return newRef;
        function constructStreamPlaybackObservation() {
            var observation = observationRef.getValue();
            var lastSpeed = speed.getValue();
            var pendingPosition;
            if (!initialSeekPerformed.getValue()) {
                pendingPosition = startTime;
            }
            else if (!manifest.isDynamic || manifest.isLastPeriodKnown) {
                // HACK: When the position is actually further than the maximum
                // position for a finished content, we actually want to be loading
                // the last segment before ending.
                // For now, this behavior is implicitely forced by making as if we
                // want to seek one second before the period's end (despite never
                // doing it).
                var lastPeriod = manifest.periods[manifest.periods.length - 1];
                if (lastPeriod !== undefined &&
                    lastPeriod.end !== undefined &&
                    observation.position > lastPeriod.end) {
                    pendingPosition = lastPeriod.end - 1;
                }
            }
            return {
                // TODO more exact according to the current Adaptation chosen?
                maximumPosition: manifest.getMaximumSafePosition(),
                position: {
                    last: observation.position,
                    pending: pendingPosition,
                },
                duration: observation.duration,
                paused: {
                    last: observation.paused,
                    pending: initialPlayPerformed.getValue() ? undefined :
                        !autoPlay === observation.paused ? undefined :
                            !autoPlay,
                },
                readyState: observation.readyState,
                speed: lastSpeed,
            };
        }
        function emitStreamPlaybackObservation() {
            newRef.setValue(constructStreamPlaybackObservation());
        }
    });
}
