/*
 * Copyright (C) 2013 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.hardware.camera2.utils;

import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR;
import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
import static android.system.OsConstants.*;

import android.os.DeadObjectException;
import android.os.RemoteException;

import java.lang.reflect.Method;

/**
 * Translate camera device status_t return values into exceptions.
 *
 * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance
 * @hide
 */
public class CameraBinderDecorator {

    public static final int NO_ERROR = 0;
    public static final int PERMISSION_DENIED = -EPERM;
    public static final int ALREADY_EXISTS = -EEXIST;
    public static final int BAD_VALUE = -EINVAL;
    public static final int DEAD_OBJECT = -ENOSYS;
    public static final int INVALID_OPERATION = -EPIPE;
    public static final int TIMED_OUT = -ETIMEDOUT;

    /**
     * TODO: add as error codes in Errors.h
     * - POLICY_PROHIBITS
     * - RESOURCE_BUSY
     * - NO_SUCH_DEVICE
     * - NOT_SUPPORTED
     * - TOO_MANY_USERS
     */

    static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {

        @Override
        public void onBeforeInvocation(Method m, Object[] args) {
        }

        @Override
        public void onAfterInvocation(Method m, Object[] args, Object result) {
            // int return type => status_t => convert to exception
            if (m.getReturnType() == Integer.TYPE) {
                int returnValue = (Integer) result;
                throwOnError(returnValue);
            }
        }

        @Override
        public boolean onCatchException(Method m, Object[] args, Throwable t) {

            if (t instanceof DeadObjectException) {
                throw new CameraRuntimeException(CAMERA_DISCONNECTED,
                        "Process hosting the camera service has died unexpectedly",
                        t);
            } else if (t instanceof RemoteException) {
                throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
                        " which should never happen.", t);
            }

            return false;
        }

        @Override
        public void onFinally(Method m, Object[] args) {
        }

    }

    /**
     * Throw error codes returned by the camera service as exceptions.
     *
     * @param errorFlag error to throw as an exception.
     */
    public static void throwOnError(int errorFlag) {
        if (errorFlag == NO_ERROR) {
            return;
        } else if (errorFlag == PERMISSION_DENIED) {
            throw new SecurityException("Lacking privileges to access camera service");
        } else if (errorFlag == ALREADY_EXISTS) {
            // This should be handled at the call site. Typically this isn't bad,
            // just means we tried to do an operation that already completed.
            return;
        } else if (errorFlag == BAD_VALUE) {
            throw new IllegalArgumentException("Bad argument passed to camera service");
        } else if (errorFlag == DEAD_OBJECT) {
            throw new CameraRuntimeException(CAMERA_DISCONNECTED);
        } else if (errorFlag == TIMED_OUT) {
            throw new CameraRuntimeException(CAMERA_ERROR,
                    "Operation timed out in camera service");
        } else if (errorFlag == -EACCES) {
            throw new CameraRuntimeException(CAMERA_DISABLED);
        } else if (errorFlag == -EBUSY) {
            throw new CameraRuntimeException(CAMERA_IN_USE);
        } else if (errorFlag == -EUSERS) {
            throw new CameraRuntimeException(MAX_CAMERAS_IN_USE);
        } else if (errorFlag == -ENODEV) {
            throw new CameraRuntimeException(CAMERA_DISCONNECTED);
        } else if (errorFlag == -EOPNOTSUPP) {
            throw new CameraRuntimeException(CAMERA_DEPRECATED_HAL);
        } else if (errorFlag == INVALID_OPERATION) {
            throw new CameraRuntimeException(CAMERA_ERROR,
                    "Illegal state encountered in camera service.");
        }

        /**
         * Trap the rest of the negative return values. If we have known
         * error codes i.e. ALREADY_EXISTS that aren't really runtime
         * errors, then add them to the top switch statement
         */
        if (errorFlag < 0) {
            throw new CameraRuntimeException(CAMERA_ERROR,
                    String.format("Unknown camera device error %d", errorFlag));
        }
    }

    /**
     * <p>
     * Wraps the type T with a proxy that will check 'status_t' return codes
     * from the native side of the camera service, and throw Java exceptions
     * automatically based on the code.
     * </p>
     * <p>
     * In addition it also rewrites binder's RemoteException into either a
     * CameraAccessException or an UnsupportedOperationException.
     * </p>
     * <p>
     * As a result of calling any method on the proxy, RemoteException is
     * guaranteed never to be thrown.
     * </p>
     *
     * @param obj object that will serve as the target for all method calls
     * @param <T> the type of the element you want to wrap. This must be an interface.
     * @return a proxy that will intercept all invocations to obj
     */
    public static <T> T newInstance(T obj) {
        return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener());
    }
}
