/*
 * Copyright 2015 Rockchip Electronics Co. LTD
 *
 * 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.
 */
 
#ifndef __CAMERA2_READER_H__
#define __CAMERA2_READER_H__
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
 
#include <camera/NdkCameraManager.h>
#include <camera/NdkCameraError.h>
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraMetadataTags.h>
#include <media/NdkImageReader.h>
#include <android/log.h>
#define  LOG_TAG    "native-camera2-jni"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define FMT_NUM_PLANES 1
 
// struct CameraParam
// {
//     int id;
//     const char *device;
//     RK_U32 bufcnt;
//     RK_U32 width;
//     RK_U32 height;
//     MppFrameFormat fmt;
// };

#include <string>
 
class Camera2Reader
{
private:
    AImageReader *mAImageReader;
    ANativeWindow *theNativeWindow;
    ACameraDevice *cameraDevice;
    ACaptureRequest *captureRequest;
    ACameraOutputTarget *cameraOutputTarget;
    ACaptureSessionOutput *sessionOutput;
    ACaptureSessionOutputContainer *captureSessionOutputContainer;
    ACameraCaptureSession *captureSession;
 
    ACameraDevice_StateCallbacks deviceStateCallbacks;
    ACameraCaptureSession_stateCallbacks captureSessionStateCallbacks;
 
    int sessionSequenceId;
 
    int mCameraId = 0;
    char mDevice[20];
    int mBufcnt;
    int mWidth;
    int mHeight;
    int mFmt;

    std::string mPath;
    std::string mFileName;

    unsigned char *mYuv720p = NULL;
    unsigned char *mYuv420i = NULL;
    unsigned char *mArgb1080p = NULL;
    // Create a new context to capture frames from <fname>. Returns NULL on error.
    int Init(const char *device, int bufcnt, int width, int height, int fmt);
    
    // Stop capturing and free a context.
    int Deinit();
    bool readyToRun();
    bool threadLoop();
    ACameraCaptureSession_stateCallbacks *GetSessionListener();
    void ImageCallback(AImageReader *reader);
    static void OnImageCallback(void *ctx, AImageReader *reader);
 
    static void camera_device_on_disconnected(void *context, ACameraDevice *device)
    {
        LOGI("Camera(id: %s) is diconnected.\n", ACameraDevice_getId(device));
    }
 
    static void camera_device_on_error(void *context, ACameraDevice *device, int error)
    {
        LOGI("Error(code: %d) on Camera(id: %s).\n", error, ACameraDevice_getId(device));
    }
 
    static void capture_session_on_ready(void *context, ACameraCaptureSession *session)
    {
        LOGI("Session is ready. %p\n", session);
    }
 
    static void capture_session_on_active(void *context, ACameraCaptureSession *session)
    {
        LOGI("Session is activated. %p\n", session);
    }
 
    static void capture_session_on_closed(void *context, ACameraCaptureSession *session)
    {
        LOGI("Session is closed. %p\n", session);
    }

    static void WriteFile(Camera2Reader* pThis, AImage *image, const std::string& path);
 
public:
    bool Open(const char* path, const char* fileName);
    Camera2Reader(const char *device, int bufcnt, int width, int height, int fmt);
    Camera2Reader(int cameraId);
    void *readImage(int chn);
    // Camera2Reader &operator=(CameraParam *cameraParam);
    ~Camera2Reader();
    void start();
    void stop();
};
#endif /* __CAMERA_READER_H__ */
