/*
 * Copyright (C) 2014 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.
 */
#include "minui.h"
#include "graphics.h"
#include "minui_log.h"
#include "../osd/osd_hw.h"
#include <video_fb.h>

#define DOUBLE_BUFFER
/* Graphic Device */
static GraphicDevice *gdev = NULL;

static GRSurface* fbdev_init(void);
static GRSurface* fbdev_flip(void);
static void fbdev_blank(bool);
static void fbdev_exit(void);
extern int video_scale_bitmap(void);
static GRSurface gr_framebuffer[2];
static bool double_buffered;
static int displayed_buffer;
GRSurface* gr_draw = NULL;

static minui_backend my_backend = {
	.init = fbdev_init,
	.flip = fbdev_flip,
	.blank = fbdev_blank,
	.exit = fbdev_exit,
};

static unsigned long env_strtoul(const char *name, int base)
{
	unsigned long ret = 0;

	ret = getenv_ulong(name, base, 0);

	if (base == 16)
		ui_logd("%s: 0x%lx\n", name, ret);
	else if (base == 10)
		ui_logd("%s: %ld\n", name, ret);

	return ret;
}

minui_backend* open_fbdev(void)
{
	return &my_backend;
}

static void fbdev_blank(bool blank)
{
	int osd_index;

	osd_index = get_osd_layer();
	if (osd_index >= 0)
		osd_enable_hw(osd_index, blank);
}

static void set_displayed_framebuffer(unsigned n)
{
	int osd_index;

	if ( n > 1 || !double_buffered)
		return;
	osd_index = get_osd_layer();

	if (double_buffered) {
		osd_pan_display_hw(osd_index, 0, n * gr_framebuffer[0].height);
		ui_logd("pan display:yoffset=%d\n", n * gr_framebuffer[0].height);
	}
	displayed_buffer = n;
}

static char * getenv_str(const char *name)
{
	char *str = NULL;
	if (!name) {
		ui_loge("read env, name is NULL\n");
		return NULL;
	}
	str = getenv(name);

	return str ? str : NULL;
}

static GRSurface* fbdev_init(void)
{
	u32 color_index, display_bpp;
	char buf[16] = {};
	char *outputmode = NULL;
	char mode[64];

	outputmode = getenv_str("outputmode");
	if (!outputmode)
		return NULL;

	memset(mode, 0, sizeof(mode));
	snprintf(mode, sizeof(mode), "vout output %s", outputmode);
	run_command(mode, 0);

	color_index = env_strtoul("display_color_index", 10);
	display_bpp = env_strtoul("display_bpp", 10);

	setenv("display_color_index", "32");
	setenv("display_bpp", "32");
	gdev = video_hw_init(MIDDLE_MODE);
	if (gdev == NULL) {
		ui_loge("Initialize video device failed!\n");
		return NULL;
	}
	gr_framebuffer[0].width = gdev->fb_width;
	gr_framebuffer[0].height = gdev->fb_height;
	gr_framebuffer[0].row_bytes = gdev->fb_width * gdev->gdfBytesPP;
	gr_framebuffer[0].pixel_bytes = gdev->gdfBytesPP;
	gr_framebuffer[0].data = (unsigned char *)(long long)(gdev->frameAdrs);
	memset(gr_framebuffer[0].data, 0,
		gr_framebuffer[0].height * gr_framebuffer[0].row_bytes);

#ifdef DOUBLE_BUFFER
	double_buffered = true;
	memcpy(gr_framebuffer+1, gr_framebuffer, sizeof(GRSurface));
	gr_framebuffer[1].data = gr_framebuffer[0].data +
		gr_framebuffer[0].height * gr_framebuffer[0].row_bytes;
	gr_draw = gr_framebuffer+1;
#else
	double_buffered = false;
	// Without double-buffering, we allocate RAM for a buffer to
	// draw in, and then "flipping" the buffer consists of a
	// memcpy from the buffer we allocated to the framebuffer.

	gr_draw = (GRSurface*) malloc(sizeof(GRSurface));
	memcpy(gr_draw, gr_framebuffer, sizeof(GRSurface));
	gr_draw->data = (unsigned char*) malloc(gr_draw->height * gr_draw->row_bytes);
	if (!gr_draw->data) {
		ui_loge("failed to allocate in-memory surface");
		return NULL;
	}
#endif
	memset(gr_draw->data, 0, gr_draw->height * gr_draw->row_bytes);
	set_displayed_framebuffer(0);

	ui_logi("framebuffer: (%d x %d)\n", gr_draw->width, gr_draw->height);

	fbdev_blank(true);
	fbdev_blank(false);

#ifdef CONFIG_OSD_SCALE_ENABLE
	video_scale_bitmap();
#endif
	sprintf(buf, "%d", color_index);
	setenv("display_color_index", buf);
	sprintf(buf, "%d", display_bpp);
	setenv("display_bpp", buf);
	return gr_draw;
}

static GRSurface* fbdev_flip(void)
{
	if (double_buffered) {
		// Change gr_draw to point to the buffer currently displayed,
		// then flip the driver so we're displaying the other buffer
		// instead.
		ui_logd("fbdev_flip:gr_draw=0x%lx\n",
			(unsigned long)(unsigned char*)gr_draw->data);
		flush_cache((unsigned long)gr_draw->data, gr_draw->row_bytes * gr_draw->height);
		gr_draw = gr_framebuffer + displayed_buffer;
		set_displayed_framebuffer(1-displayed_buffer);
	} else {
		// Copy from the in-memory surface to the framebuffer.
		set_displayed_framebuffer(0);
		memcpy(gr_framebuffer[0].data, gr_draw->data,
			gr_draw->height * gr_draw->row_bytes);
		ui_logd("flip: \n");
	}
	return gr_draw;
}

static void fbdev_exit(void)
{
	if (!double_buffered && gr_draw) {
		free(gr_draw->data);
		free(gr_draw);
	}
	gr_draw = NULL;
}
