#ifndef __PHONE_DEVICE2_H__
#define __PHONE_DEVICE2_H__

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <map>
#include <atomic>

#include <camera/NdkCameraManager.h>
#include <camera/NdkCameraError.h>
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraMetadataTags.h>
#include <media/NdkImageReader.h>
#include <Client/Device.h>
#include <string>

#include "camera2/Camera2Helper.h"

class CPhoneDevice2 : public IDevice
{
public:
	CPhoneDevice2(JavaVM* vm, jobject service);
	virtual ~CPhoneDevice2();

    virtual void SetListener(IListener* listener);
	virtual bool UpdateTime(time_t ts);
    virtual bool Reboot();
    virtual timer_uid_t RegisterHeartbeat(unsigned int timerType, unsigned int timeout);
	virtual bool TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path);
    virtual timer_uid_t RegisterTimer(unsigned int timerType, unsigned int timeout);
    virtual bool UnregisterTimer(timer_uid_t uid);

	virtual bool FireTimer(timer_uid_t uid);
protected:

	ACameraCaptureSession_stateCallbacks *GetSessionListener();
	std::string GetFileName() const;

	bool SendBroadcastMessage(std::string action, int value);
	bool MatchCaptureSizeRequest(ACameraManager *cameraManager, const char *selectedCameraId, unsigned int width, unsigned int height, uint32_t cameraOrientation_,
											   ImageFormat* resCap);
    bool DisplayImage(ANativeWindow_Buffer* buf, AImage* image);

    void PresentImage(ANativeWindow_Buffer* buf, AImage* image);
    void PresentImage90(ANativeWindow_Buffer* buf, AImage* image);
    void PresentImage180(ANativeWindow_Buffer* buf, AImage* image);
    void PresentImage270(ANativeWindow_Buffer* buf, AImage* image);

	static void camera_device_on_disconnected(void *context, ACameraDevice *device);
	static void camera_device_on_error(void *context, ACameraDevice *device, int error);
	static void capture_session_on_ready(void *context, ACameraCaptureSession *session);
	static void capture_session_on_active(void *context, ACameraCaptureSession *session);
	static void capture_session_on_closed(void *context, ACameraCaptureSession *session);

	void ImageCallback(AImageReader *reader);
	static void OnImageCallback(void *ctx, AImageReader *reader);
    bool WriteFile(AImage *image, const string& path);
	static bool WriteFile(CPhoneDevice2* pThis, AImage *image);

    inline bool TakePhotoCb(bool res, const IDevice::PHOTO_INFO& photoInfo, const string& path, time_t photoTime)
    {
        if (m_listener != NULL)
        {
            std::vector<IDevice::RECOG_OBJECT> objects;
            return m_listener->OnPhotoTaken(res, photoInfo, path, photoTime, objects);
        }

        return false;
    }



protected:

    JavaVM* m_vm;
    jobject m_javaService;

	jmethodID mRegisterTimerMid;
	jmethodID mRegisterHeartbeatMid;
	jmethodID mUnregisterTimerMid;
    jmethodID mUpdateTimeMid;

	std::string mPath;
    IDevice::PHOTO_INFO mPhotoInfo;
    IListener* m_listener;

	atomic_ulong m_timerUidFeed;
	std::map<IDevice::timer_uid_t, unsigned long> mTimers;

	AImageReader *mAImageReader;
	ANativeWindow *theNativeWindow;
	ACameraDevice *cameraDevice;
	ACaptureRequest *captureRequest;
	ACameraOutputTarget *cameraOutputTarget;
	ACaptureSessionOutput *sessionOutput;
	ACaptureSessionOutputContainer *captureSessionOutputContainer;
	ACameraCaptureSession *captureSession;

	ACameraDevice_StateCallbacks deviceStateCallbacks;
	ACameraCaptureSession_stateCallbacks captureSessionStateCallbacks;

	DisplayDimension mDisplayDimension;
	int32_t presentRotation_;

	int32_t imageHeight_;
	int32_t imageWidth_;

    uint8_t* imageBuffer_;
    int32_t yStride, uvStride;
    uint8_t *yPixel, *uPixel, *vPixel;
    int32_t yLen, uLen, vLen;
	int32_t uvPixelStride;


};


#endif // __PHONE_DEVICE2_H__