/* Copyright 2017-present Renesas Electronics Corporation and other contributors
 *
 * 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 PERIPHERAL_IO_4MBED_INCL
#define PERIPHERAL_IO_4MBED_INCL

#ifdef __cplusplus
extern "C" {
#endif

#define P4_API(type,func)	type P4(func)
#define VIDEO_API		P4_API
#define DISPLAY_API		P4_API
#define JPEG_API		P4_API
#define GRAPHICS_API	P4_API

// VIDEO
typedef void* P4(video_h);

typedef enum {
	VIDEO_PIXELFORMAT_YCBCR422,
	VIDEO_PIXELFORMAT_RGB565,
	VIDEO_PIXELFORMAT_RGB888,
	VIDEO_PIXELFORMAT_MAX,
} video_pixel_format_t;

typedef enum {
	DEVICETYPE_CMOSCAMERA,
	DEVICETYPE_COMPOSITESIGNAL,
	DEVICETYPE_MAX,
} device_type_t;

typedef enum {
	CAMERATYPE_OV7725,
	CAMERATYPE_MAX,
} camera_type_t;

typedef enum {
	CHANNEL_0,
	CHANNEL_1,
	CHANNEL_MAX,
} channel_num_t;

typedef enum {
	SIGNALFORMAT_NTSC,
	SIGNALFORMAT_PAL,
	SIGNALFORMAT_MAX,
} signal_format_t;

typedef struct {
	uint32_t width;
	uint32_t height;
	uint32_t pixel_bytes;
	uint8_t* frame_buffer;

	device_type_t device;
	camera_type_t camera;
	video_pixel_format_t pixel_format;
	signal_format_t signal_format;
	channel_num_t channel;
} video_source_t;

VIDEO_API(P4(video_h), video_open(video_source_t video_source));
VIDEO_API(bool, video_start(P4(video_h) handle, void* buf));
VIDEO_API(bool, video_stop(P4(video_h) handle));
VIDEO_API(bool, video_close(P4(video_h) handle));

// DISPLAY(LCD)
typedef void* P4(lcd_h);

typedef enum {
	DISPLAY_PIXELFORMAT_YCBCR422,
	DISPLAY_PIXELFORMAT_RGB565,
	DISPLAY_PIXELFORMAT_RGB888,
	DISPLAY_PIXELFORMAT_ARGB8888,
	DISPLAY_PIXELFORMAT_ARGB4444,
	DISPLAY_PIXELFORMAT_MAX,
} display_pixel_format_t;

typedef enum {
	LCDTYPE_4_3INCH,
	LCDTYPE_MAX,
} lcd_type_t;

typedef enum {
	LCDLAYER_0,
	LCDLAYER_1,
	LCDLAYER_2,
	LCDLAYER_3,
	LCDLAYER_MAX,
} lcd_layer_id_t;

typedef struct {
	lcd_layer_id_t id;
	display_pixel_format_t buffer_format;
	uint32_t pixel_bytes;
	uint8_t* frame_buffer;
} lcd_layer_t;

typedef struct {
	lcd_type_t type;

	uint32_t width;
	uint32_t height;
} lcd_t;

DISPLAY_API(P4(lcd_h), lcd_open(lcd_t *lcd));
DISPLAY_API(bool, lcd_close(P4(lcd_h) handle));
DISPLAY_API(bool, lcd_start(P4(lcd_h) handle, lcd_layer_t lcd_layer));
DISPLAY_API(bool, lcd_stop(P4(lcd_h) handle, lcd_layer_id_t id));
DISPLAY_API(bool, lcd_update(P4(lcd_h) handle, lcd_layer_t lcd_layer));

// JPEG
typedef void* P4(jpeg_h);

typedef enum {
	JPEG_PIXELFORMAT_YCBCR422,	/* encode, decode */
	JPEG_PIXELFORMAT_ARGB8888,	/* decode */
	JPEG_PIXELFORMAT_RGB565,	/* decode */
	JPEG_PIXELFORMAT_MAX,
} jpeg_pixel_format_t;

typedef struct {
	uint32_t width;
	uint32_t height;
	jpeg_pixel_format_t pixel_format;
	uint32_t alpha;

	struct {
		uint32_t len;
		uint8_t* buf;
	} src, dst;
} jpeg_convert_data_t;

JPEG_API(int, jpeg_encode(jpeg_convert_data_t encode_data));
JPEG_API(bool, jpeg_decode(jpeg_convert_data_t decode_data));

// GRAPHICS
typedef void* P4(graphics_h);

GRAPHICS_API(P4(graphics_h), initFrameBuffer(char *buf, int width, int height, int format));
GRAPHICS_API(int, deinitFrameBuffer(P4(graphics_h) handle));
GRAPHICS_API(int, drawLine(P4(graphics_h) handle, int startX, int startY, int endX, int endY, uint32_t color));
GRAPHICS_API(int, drawRect(P4(graphics_h) handle, int x, int y, int width, int height, uint32_t color, bool fill));
GRAPHICS_API(int, drawArc(P4(graphics_h) handle, int centerX, int centerY, int radius, int startAngle, int endAngle, uint32_t color));
GRAPHICS_API(int, drawCircle(P4(graphics_h) handle, int centerX, int centerY, int radius, uint32_t color, bool fill));
GRAPHICS_API(int, drawEllipse(P4(graphics_h) handle, int centerX, int centerY, int radiusX, int radiusY, uint32_t color, bool fill));
GRAPHICS_API(int, drawPolygon(P4(graphics_h) handle, int centerX, int centerY, int radius, int sides, uint32_t color, bool fill));
GRAPHICS_API(int, drawText(P4(graphics_h) handle, char* text, int x, int y, int size, uint32_t color, uint32_t background));
GRAPHICS_API(int, drawImage(P4(graphics_h) handle, char* image, int x, int y, int width, int height));

#undef GRAPHICS_API
#undef JPEG_API
#undef DISPLAY_API
#undef VIDEO_API

#if !defined( POSIX4_ITSELF )

	// functions
	#define video_open					P4(video_open)
	#define video_start					P4(video_start)
	#define video_stop					P4(video_stop)
	#define video_close					P4(video_close)
	#define lcd_open					P4(lcd_open)
	#define lcd_close					P4(lcd_close)
	#define lcd_start					P4(lcd_start)
	#define lcd_stop					P4(lcd_stop)
	#define lcd_update					P4(lcd_update)
	#define jpeg_encode					P4(jpeg_encode)
	#define jpeg_decode					P4(jpeg_decode)
	
	#define initFrameBuffer				P4(initFrameBuffer)
	#define deinitFrameBuffer			P4(deinitFrameBuffer)
	#define drawLine					P4(drawLine)
	#define drawRect					P4(drawRect)
	#define drawArc						P4(drawArc)
	#define drawCircle					P4(drawCircle)
	#define drawEllipse					P4(drawEllipse)
	#define drawPolygon					P4(drawPolygon)
	#define drawText					P4(drawText)
	#define drawImage					P4(drawImage)

	// typedefs
	#define video_h						P4(video_h)
	#define lcd_h						P4(lcd_h)
	#define jpeg_h						P4(jpeg_h)
	#define graphics_h					P4(graphics_h)

#endif	// #if !defined( POSIX4_ITSELF )

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus

namespace mbed {

	namespace video {
		P4(video_h) open(video_source_t video_source);
		bool close(P4(video_h) handle);
		bool start(P4(video_h) handle, void* buf);
		bool stop(P4(video_h) handle);
	}	// namespace video

	namespace lcd {
		P4(lcd_h) open(lcd_t *lcd);
		bool close(P4(lcd_h) handle);
		bool start(P4(lcd_h) handle, lcd_layer_t lcd_layer);
		bool stop(P4(lcd_h) handle, lcd_layer_id_t id);
		bool update(P4(lcd_h) handle, lcd_layer_t id);
	}	// namespace lcd

	namespace jpeg {
		int encode(jpeg_convert_data_t encode_data);
		bool decode(jpeg_convert_data_t decode_data);
	}	// namespace jpeg

	namespace graphics {
		P4(graphics_h) initFrameBuffer(char *buf, int width, int height, int format);
		int deinitFrameBuffer(P4(graphics_h) handle);
		int drawLine(P4(graphics_h) handle, int startX, int startY, int endX, int endY, uint32_t color);
		int drawRect(P4(graphics_h) handle, int x, int y, int width, int height, uint32_t color, bool fill);
		int drawArc(P4(graphics_h) handle, int centerX, int centerY, int radius, int startAngle, int endAngle, uint32_t color);
		int drawCircle(P4(graphics_h) handle, int centerX, int centerY, int radius, uint32_t color, bool fill);
		int drawEllipse(P4(graphics_h) handle, int centerX, int centerY, int radiusX, int radiusY, uint32_t color, bool fill);
		int drawPolygon(P4(graphics_h) handle, int centerX, int centerY, int radius, int sides, uint32_t color, bool fill);
		int drawText(P4(graphics_h) handle, char* text, int x, int y, int size, uint32_t color, uint32_t background);
		int drawImage(P4(graphics_h) handle, char* image, int x, int y, int width, int height);
	}	// namespace graphics

}	// namespace mbed

using namespace mbed;

#endif

#endif	// #ifndef PERIPHERAL_IO_4MBED_INCL
