/*
 * Copyright 2021 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 androidx.camera.video;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Consumer;
import androidx.core.util.Preconditions;

import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Provides controls for the currently active recording.
 */
public final class ActiveRecording extends Recording {

    private final AtomicBoolean mIsFinalized = new AtomicBoolean(false);

    ActiveRecording(@NonNull Recorder recorder, @NonNull OutputOptions options,
            @Nullable Executor callbackExecutor, @Nullable Consumer<VideoRecordEvent> listener) {
        super(recorder, options, callbackExecutor, listener);
    }

    /**
     * Creates an {@link ActiveRecording} from a {@link PendingRecording}.
     */
    @NonNull
    static ActiveRecording from(@NonNull PendingRecording pendingRecording) {
        Preconditions.checkNotNull(pendingRecording, "The given PendingRecording cannot be null.");
        return new ActiveRecording(pendingRecording.getRecorder(),
                pendingRecording.getOutputOptions(), pendingRecording.getCallbackExecutor(),
                pendingRecording.getEventListener());
    }

    /**
     * Pauses the current recording if active.
     *
     * <p>If the recording is already paused or has been finalized internally, this is a no-op.
     */
    public void pause() {
        if (mIsFinalized.get()) {
            return;
        }
        getRecorder().pause();
    }

    /**
     * Resumes the current recording if paused.
     *
     * <p>If the recording is running or has been finalized internally, this is a no-op.
     */
    public void resume() {
        if (mIsFinalized.get()) {
            return;
        }
        getRecorder().resume();
    }

    /**
     * Stops the recording.
     *
     * <p>Once stop, all methods of this ActiveRecording will be no-op.
     *
     * <p>Once an ActiveRecording has been stopped, the next recording can be started with
     * {@link PendingRecording#start()}.
     *
     * <p>If the recording is finalized internally, this is a no-op.
     */
    public void stop() {
        if (mIsFinalized.getAndSet(true)) {
            return;
        }
        getRecorder().stop();
    }

    @Override
    void updateVideoRecordEvent(@NonNull VideoRecordEvent event) {
        if (event instanceof VideoRecordEvent.Finalize) {
            mIsFinalized.set(true);
        }
        super.updateVideoRecordEvent(event);
    }
}

@@ -1003,16 +1003,207 @@
 ding %7B%0A%0A
+    // Indicates the recording has been explicitly stopped by users.%0A    private final AtomicBoolean mIsStopped = new AtomicBoolean(false);%0A    // Indicates the recording has been finalized.%0A
     priv
@@ -2107,17 +2107,18 @@
 cording 
-i
+ha
 s alread
@@ -2119,16 +2119,21 @@
 already 
+been 
 paused o
@@ -2166,32 +2166,39 @@
 nally, this is a
+%0A     *
  no-op.%0A     */%0A
@@ -2199,35 +2199,236 @@
    *
-/%0A    public void pause() %7B
+%0A     * @throws IllegalStateException if the recording has been stopped.%0A     */%0A    public void pause() %7B%0A        if (mIsStopped.get()) %7B%0A            throw new IllegalStateException(%22The recording has been stopped.%22);%0A        %7D
 %0A   
@@ -2623,15 +2623,14 @@
  is 
-running
+active
  or 
@@ -2687,36 +2687,237 @@
    *
-/%0A    public void resume() %7B
+%0A     * @throws IllegalStateException if the recording has been stopped.%0A     */%0A    public void resume() %7B%0A        if (mIsStopped.get()) %7B%0A            throw new IllegalStateException(%22The recording has been stopped.%22);%0A        %7D
 %0A   
@@ -3084,16 +3084,22 @@
 op, all 
+other 
 methods 
@@ -3131,16 +3131,53 @@
 ill 
-be no-op
+throw an%0A     * %7B@link IllegalStateException%7D
 .%0A  
@@ -3347,18 +3347,52 @@
 cording 
-is
+has already been stopped or has been
  finaliz
@@ -3407,32 +3407,39 @@
 nally, this is a
+%0A     *
  no-op.%0A     */%0A
@@ -3474,31 +3474,29 @@
      if (mIs
-Finaliz
+Stopp
 ed.getAndSet
@@ -3501,16 +3501,38 @@
 et(true)
+ %7C%7C mIsFinalized.get()
 ) %7B%0A    

Throw an exception if an ActiveRecording is being operated after stopped.