/*
 * Copyright 2012 Google Inc.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but without any warranty; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <assert.h>
#include <vboot_api.h>
#include <vboot_struct.h>

#include "base/graphics/graphics.h"
#include "drivers/board/board.h"
#include "drivers/console/display.h"
#include "drivers/display/display.h"
#include "vboot/board.h"
#include "vboot/firmware_id.h"
#include "vboot/util/commonparams.h"

VbError_t VbExDisplayInit(uint32_t *width, uint32_t *height)
{
	DisplayOps *display = board_display();

	if (display_dimensions(display, height, width))
		return VBERROR_UNKNOWN;

	return VBERROR_SUCCESS;
}

VbError_t VbExDisplayBacklight(uint8_t enable)
{
	printf("Ignoring VbExDisplayBacklight.\n");
	return VBERROR_SUCCESS;
}

static void print_string(const char *str)
{
	while (*str)
		display_console_put_char(*str++);
}

void print_on_center(const char *msg)
{
	uint32_t rows, cols;
	display_console_dimensions(&rows, &cols);
	display_console_set_cursor((cols - strlen(msg)) / 2, rows / 2);
	print_string(msg);
}

VbError_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale)
{
	const char *msg = NULL;

	/*
	 * Show the debug messages for development. It is a backup method
	 * when GBB does not contain a full set of bitmaps.
	 */
	switch (screen_type) {
	case VB_SCREEN_BLANK:
		{
			const DcColor Black = {
				.red = 0,
				.green = 0,
				.blue = 0,
			};

			// clear the screen
			DisplayOps *display = board_display();
			uint32_t height, width;
			if (display_dimensions(display, &height, &width) ||
			    display_fill(display, 0, 0,
					 height, width, &Black)) {
				return VBERROR_UNKNOWN;
			}
		}
		break;
	case VB_SCREEN_DEVELOPER_WARNING:
		msg = "developer mode warning";
		break;
	case VB_SCREEN_DEVELOPER_EGG:
		msg = "easter egg";
		break;
	case VB_SCREEN_RECOVERY_REMOVE:
		msg = "remove inserted devices";
		break;
	case VB_SCREEN_RECOVERY_INSERT:
		msg = "insert recovery image";
		break;
	case VB_SCREEN_RECOVERY_NO_GOOD:
		msg = "insert image invalid";
		break;
	case VB_SCREEN_WAIT:
		msg = "wait for ec update";
		break;
	default:
		printf("Not a valid screen type: %d.\n", screen_type);
		return VBERROR_INVALID_SCREEN_INDEX;
	}

	if (msg)
		print_on_center(msg);

	return VBERROR_SUCCESS;
}

VbError_t VbExDisplayImage(uint32_t x, uint32_t y,
			   void *buffer, uint32_t buffersize)
{
	static DcBitmap image;

	if (graphics_load_bitmap_file(&image, buffer))
		return VBERROR_UNKNOWN;

	int ret = display_draw(board_display(), x, y, &image);

	free(image.pixels);
	image.pixels = NULL;

	return ret ? VBERROR_UNKNOWN : VBERROR_SUCCESS;
}

VbError_t VbExDisplaySetDimension(uint32_t width, uint32_t height)
{
	// TODO(hungte) Shift or scale images if width/height is not equal to
	// get_sysinfo()->framebuffer->{x,y}_resolution.
	return VBERROR_SUCCESS;
}

VbError_t VbExDisplayDebugInfo(const char *info_str)
{
	if (display_console_set_cursor(0, 0))
		return VBERROR_UNKNOWN;
	print_string(info_str);

	print_string("read-only firmware id: ");
	const char *id = firmware_id_for(VDAT_RO, NULL);
	if (!id)
		id = "NOT FOUND";
	print_string(id);
	print_string("\n");

	print_string("active firmware id: ");
	id = firmware_id_active(NULL);
	if (!id)
		id = "NOT FOUND";
	print_string(id);
	print_string("\n");

	return VBERROR_SUCCESS;
}

VbError_t VbExGetLocalizationCount(uint32_t *count)
{
	if (board_storage_locale_count(count))
		return VBERROR_UNKNOWN;
	else
		return VBERROR_SUCCESS;
}
