/*
 * Copyright 2016 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>

#include "base/container_of.h"
#include "base/graphics/font8x16.h"
#include "base/graphics/graphics.h"
#include "base/init_funcs.h"
#include "base/list.h"
#include "base/xalloc.h"
#include "drivers/board/board.h"
#include "drivers/console/console.h"
#include "drivers/console/display.h"

static const DcColor display_console_background = {
	// Black.
	.red = 0,
	.green = 0,
	.blue = 0,
};

static const DcColor display_console_foreground = {
	// Gray.
	.red = 0xaa,
	.green = 0xaa,
	.blue = 0xaa,
};

typedef struct {
	Console console;

	DisplayOps *display;

	int32_t cursor_x;
	int32_t cursor_y;

	uint32_t display_height;
	uint32_t display_width;

	DcFont *font;

	uint32_t height;
	uint32_t width;
} DisplayConsole;

static int display_console_initialize(DisplayConsole *console)
{
	DisplayOps *display = board_display();

	uint32_t height, width;
	if (display_dimensions(display, &height, &width))
		return 1;

	console->cursor_x = 0;
	console->cursor_y = 0;

	console->display_height = height;
	console->display_width = width;

	console->font = &dc_font_8x16;

	console->height = console->display_height / console->font->height;
	console->width = console->display_width / console->font->width;

	console->display = display;

	return 0;
}

static int display_console_scroll_up(DisplayConsole *console)
{
	uint32_t font_height = console->font->height;

	// Scroll the text up.
	if (display_move(console->display, 0, font_height, 0, 0,
			 console->display_height - font_height,
			 console->display_width)) {
		return 1;
	}

	// Erase the last line.
	if (display_fill(console->display, 0,
			 console->display_height - font_height,
			 font_height, console->display_width,
			 &display_console_background)) {
		return 1;
	}

	return 0;
}

static int display_console_put_char_work(ConsoleOutputOps *me, unsigned int c)
{
	DisplayConsole *console =
		container_of(me, DisplayConsole, console.output);

	if (!console->display && display_console_initialize(console))
		return 1;

	static DcBitmap glyph;

	switch (c) {
	case '\r':
		console->cursor_x = 0;
		break;
	case '\n':
		console->cursor_x = 0;
		console->cursor_y++;
		break;
	case '\b':
		console->cursor_x--;
		if (console->cursor_x < 0) {
			console->cursor_y--;
			console->cursor_x = console->width;
		}
		break;
	case '\t':
		while (console->cursor_x % 8 &&
		       console->cursor_x < console->width) {
			display_console_put_char_work(me, ' ');
		}
		break;
	default:
		if (!glyph.pixels ||
		    glyph.width != console->font->width ||
		    glyph.height != console->font->height) {
			free(glyph.pixels);
			glyph.width = console->font->width;
			glyph.height = console->font->height;
			glyph.pixels = xmalloc(glyph.width * glyph.height *
					       sizeof(*glyph.pixels));
		}
		graphics_render_char(&glyph, console->font,
				     &display_console_foreground,
				     &display_console_background, c);
		uint32_t x = console->cursor_x * console->font->width;
		uint32_t y = console->cursor_y * console->font->height;
		display_draw(console->display, x, y, &glyph);

		console->cursor_x++;
	}

	if (console->cursor_x < 0)
		console->cursor_x = 0;
	if (console->cursor_y < 0)
		console->cursor_y = 0;
	if (console->cursor_x >= console->width) {
		console->cursor_x = 0;
		console->cursor_y++;
	}

	while (console->cursor_y >= console->height) {
		display_console_scroll_up(console);
		console->cursor_y--;
	}

	return 0;
}

static void display_console_put_char_cb(ConsoleOutputOps *me, unsigned int c)
{
	display_console_put_char_work(me, c);
}

static DisplayConsole display_console = {
	.console = {
		.output = {
			.putchar = &display_console_put_char_cb,
		},
	},
};

int display_console_dimensions(uint32_t *rows, uint32_t *cols)
{
	*rows = display_console.height;
	*cols = display_console.width;
	return 0;
}

int display_console_set_cursor(uint32_t x, uint32_t y)
{
	if (!display_console.display &&
	    display_console_initialize(&display_console))
		return 1;

	if (x >= display_console.width || y >= display_console.height) {
		printf("Cursor position (%d, %d) out of bounds.\n", x, y);
		return 1;
	}

	display_console.cursor_x = x;
	display_console.cursor_y = y;

	return 0;
}

int display_console_put_char(char c)
{
	return display_console_put_char_work(
		&display_console.console.output, c);
}

void display_console_attach(void)
{
	if (!display_console.console.list_node.next) {
		list_insert_after(&display_console.console.list_node,
				  &console_list);
	}
}

void display_console_detach(void)
{
	if (display_console.console.list_node.next) {
		list_remove(&display_console.console.list_node);
		display_console.console.list_node.next = NULL;
		display_console.console.list_node.prev = NULL;
	}
}
