/*
 * Copyright 2019 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.camera2.internal.util;

import android.graphics.ImageFormat;
import android.hardware.camera2.CameraDevice;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.Looper;
import android.util.Size;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraX;
import androidx.camera.core.impl.ImmediateSurface;
import androidx.camera.core.impl.SessionConfig;
import androidx.camera.core.impl.UseCaseConfig;
import androidx.camera.testing.fakes.FakeUseCase;
import androidx.camera.testing.fakes.FakeUseCaseConfig;

import java.util.Map;

/**
 * A fake {@link FakeUseCase} which contain a repeating surface.
 *
 * @hide
 */
@RestrictTo(Scope.LIBRARY)
public class FakeRepeatingUseCase extends FakeUseCase {

    /** The repeating surface. */
    private final ImageReader mImageReader =
            ImageReader.newInstance(640, 480, ImageFormat.YUV_420_888, 2);

    public FakeRepeatingUseCase(@NonNull FakeUseCaseConfig configuration,
            @NonNull CameraSelector cameraSelector) {
        super(configuration);

        FakeUseCaseConfig configWithDefaults = (FakeUseCaseConfig) getUseCaseConfig();
        mImageReader.setOnImageAvailableListener(
                new ImageReader.OnImageAvailableListener() {
                    @Override
                    public void onImageAvailable(ImageReader imageReader) {
                        Image image = imageReader.acquireLatestImage();
                        if (image != null) {
                            image.close();
                        }
                    }
                },
                new Handler(Looper.getMainLooper()));

        SessionConfig.Builder builder = SessionConfig.Builder.createFrom(configWithDefaults);
        builder.addSurface(new ImmediateSurface(mImageReader.getSurface()));

        String cameraId = CameraX.getCameraWithCameraSelector(cameraSelector);
        attachToCamera(cameraId, builder.build());
        notifyActive();
    }

    @Override
    protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable Integer lensFacing) {
        return new FakeUseCaseConfig.Builder()
                .setSessionOptionUnpacker(
                        new SessionConfig.OptionUnpacker() {
                            @Override
                            public void unpack(@NonNull UseCaseConfig<?> useCaseConfig,
                                    @NonNull SessionConfig.Builder sessionConfigBuilder) {
                                // Set the template since it is currently required by implementation
                                sessionConfigBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
                            }
                        });
    }

    @Override
    public void clear() {
        super.clear();
        mImageReader.close();
    }

    @Override
    @NonNull
    protected Map<String, Size> onSuggestedResolutionUpdated(
            @NonNull Map<String, Size> suggestedResolutionMap) {
        return suggestedResolutionMap;
    }
}

@@ -1121,16 +1121,68 @@
 ameraX;%0A
+import androidx.camera.core.impl.DeferrableSurface;%0A
 import a
@@ -1216,32 +1216,32 @@
 mediateSurface;%0A
-
 import androidx.
@@ -1312,32 +1312,98 @@
 .UseCaseConfig;%0A
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;%0A
 import androidx.
@@ -1836,24 +1836,75 @@
 0_888, 2);%0A%0A
+    private DeferrableSurface mDeferrableSurface;%0A%0A
     public F
@@ -2742,27 +2742,29 @@
     
-builder.add
+mDeferrable
 Surface
-(
+ = 
 new 
@@ -2806,16 +2806,63 @@
 rface())
+;%0A        builder.addSurface(mDeferrableSurface
 );%0A%0A    
@@ -3837,28 +3837,469 @@
     
-mImageReader.close()
+if (mDeferrableSurface != null) %7B%0A            mDeferrableSurface.setOnSurfaceDetachedListener(%0A                    CameraXExecutors.mainThreadExecutor(),%0A                    new DeferrableSurface.OnSurfaceDetachedListener() %7B%0A                        @Override%0A                        public void onSurfaceDetached() %7B%0A                            mImageReader.close();%0A                        %7D%0A                    %7D);%0A        %7D%0A        mDeferrableSurface = null
 ;%0A  

Fix ImageCapture MaxQuality test timeout