/*
 * Copyright (C) 2023 Adrien Destugues <pulkomandy@pulkomandy.tk>
 *
 * Distributed under terms of the MIT license.
 */

#include <Application.h>
#include <private/interface/ColumnListView.h>
#include <private/interface/ColumnTypes.h>
#include <GroupLayout.h>
#include <LayoutBuilder.h>
#include <MenuBar.h>
#include <Window.h>

#include <ctype.h>

#include "../BeDC.h"


class BColorStringField: public BStringField
{
public:
	BColorStringField(const char* string, rgb_color color)
		: BStringField(string)
		, fColor(color)
	{
	}

	rgb_color fColor;
};


class BColorStringColumn: public BStringColumn
{
public:
	BColorStringColumn(const char* title, float w, float minw, float maxw)
		: BStringColumn(title, w, minw, maxw, false)
	{
	}

	void DrawField(BField* field, BRect rect, BView* parent) override
	{
		BColorStringField* csField = dynamic_cast<BColorStringField*>(field);
		if (csField) {
			parent->SetHighColor(csField->fColor);
		}
		BStringColumn::DrawField(field, rect, parent);
	}
};


static char sanechar(int32 input) {
	input = input & 0xff;
	if (isprint(input))
		return (char)input;
	else
		return '.';
}


class LoggerWindow: public BWindow
{
public:
	LoggerWindow()
		: BWindow(BRect(100, 100, 900, 700), "Dev console", B_DOCUMENT_WINDOW,
			B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS)
	{
		BGroupLayout* layout = new BGroupLayout(B_VERTICAL);
		SetLayout(layout);
		layout->SetSpacing(0);

		fEventList = new BColumnListView("messages", 0, B_NO_BORDER);
		fEventList->AddColumn(new BColorStringColumn("Name", 100, 50, 200), 0);
		fEventList->AddColumn(new BColorStringColumn("Text", INT16_MAX, 50, INT16_MAX), 1);

		BLayoutBuilder::Group<>(layout)
			.SetInsets(0, -1, -1, -1)
			.Add(new BMenuBar("main menu"))
			.Add(fEventList)
		.End();
	}

	void MessageReceived(BMessage* message) override
	{
		switch(message->what) {
			case BEDC_MESSAGE:
			{
				// TODO parse all info: bedc_ver, bedc_main_type
				// bedc_ver: "1.0" (can be changed in later versions if the message format changes)
				// bedc_main_type: BEDC_BMESSAGE or BEDC_PLAIN_MESSAGE
				BString name = message->FindString("bedc_name");
				BString text = message->FindString("bedc_text");
				int8 colorEnum = message->FindInt8("bedc_color");
				int8 type = message->FindInt8("bedc_type");
				int8 main_type = message->FindInt8("bedc_main_type");

				if (type == DC_CLEAR) {
					fEventList->Clear();
					return;
				}

				if (main_type == BEDC_BMESSAGE && text.IsEmpty()) {
					int32 what = message->FindInt32("bedc_what");

					text.SetToFormat("BMessage(what=%#010x, %d, '%c%c%c%c')", what, what,
						sanechar(what >> 24), sanechar(what >> 16),
						sanechar(what >>  8), sanechar(what >>  0));
				}

				// TODO: generic BMessage handling (results in one line per item in the message)
				// TODO: separators
				//
				//
				BRow* row = new BRow();
				if (colorEnum == 0) {
					row->SetField(new BStringField(name), 0);
				} else {
					rgb_color color;
					switch(colorEnum) {
						case DC_WHITE:
							color = make_color(128, 128, 128, 255);
							break;
						case DC_BLACK:
							color = make_color(64, 64, 64, 255);
							break;
						case DC_BLUE:
							color = make_color(0, 0, 128, 255);
							break;
						case DC_RED:
							color = make_color(0, 128, 0, 255);
							break;
						case DC_YELLOW:
							color = make_color(128, 128, 0, 255);
							break;
						case DC_GREEN:
							color = make_color(128, 0, 0, 255);
							break;
					}
					row->SetField(new BColorStringField(name, color), 0);
				}

				if (type == DC_SUCCESS)
					row->SetField(new BColorStringField(text, ui_color(B_SUCCESS_COLOR)), 1);
				else if (type == DC_ERROR)
					row->SetField(new BColorStringField(text, ui_color(B_FAILURE_COLOR)), 1);
				else if (type == DC_MESSAGE)
					row->SetField(new BStringField(text), 1);
				else if (type == DC_SEPARATOR)
					row->SetField(new BStringField("-----"), 1);
				else {
					message->PrintToStream();
				}
				fEventList->AddRow(row, -1);

				if (main_type == BEDC_BMESSAGE) {
					int index = 0;
					char* nameFound;
					type_code typeFound;
					int32 countFound;
					while (message->GetInfo(B_ANY_TYPE, index++, &nameFound, &typeFound, &countFound) == B_OK) {
						// Don't display all the bedc_ internal stuff
						if (BString(nameFound).StartsWith("bedc_"))
							continue;

						for (int j = 0; j < countFound; j++) {
							name.SetToFormat("%s[%d] (%c%c%c%c)", nameFound, j,
								(typeFound >> 24) & 0xFF, (typeFound >> 16) & 0xFF,
								(typeFound >>  8) & 0xFF, (typeFound >>  0) & 0xFF
							);

							switch(typeFound) {
#if 0
	B_AFFINE_TRANSFORM_TYPE			= 'AMTX',
	B_ALIGNMENT_TYPE				= 'ALGN',
	B_ANY_TYPE						= 'ANYT',
	B_ATOM_TYPE						= 'ATOM',
	B_ATOMREF_TYPE					= 'ATMR',
	B_BOOL_TYPE						= 'BOOL',
	B_CHAR_TYPE						= 'CHAR',
	B_COLOR_8_BIT_TYPE				= 'CLRB',
	B_DOUBLE_TYPE					= 'DBLE',
	B_FLOAT_TYPE					= 'FLOT',
	B_GRAYSCALE_8_BIT_TYPE			= 'GRYB',
	B_INT16_TYPE					= 'SHRT',
	B_INT64_TYPE					= 'LLNG',
	B_INT8_TYPE						= 'BYTE',
	B_LARGE_ICON_TYPE				= 'ICON',
	B_MEDIA_PARAMETER_GROUP_TYPE	= 'BMCG',
	B_MEDIA_PARAMETER_TYPE			= 'BMCT',
	B_MEDIA_PARAMETER_WEB_TYPE		= 'BMCW',
	B_MESSAGE_TYPE					= 'MSGG',
	B_MESSENGER_TYPE				= 'MSNG',
	B_MIME_TYPE						= 'MIME',
	B_MINI_ICON_TYPE				= 'MICN',
	B_MONOCHROME_1_BIT_TYPE			= 'MNOB',
	B_OBJECT_TYPE					= 'OPTR',
	B_OFF_T_TYPE					= 'OFFT',
	B_PATTERN_TYPE					= 'PATN',
	B_POINTER_TYPE					= 'PNTR',
	B_PROPERTY_INFO_TYPE			= 'SCTD',
	B_RAW_TYPE						= 'RAWT',
	B_RECT_TYPE						= 'RECT',
	B_REF_TYPE						= 'RREF',
	B_NODE_REF_TYPE					= 'NREF',
	B_RGB_32_BIT_TYPE				= 'RGBB',
	B_RGB_COLOR_TYPE				= 'RGBC',
	B_SIZE_TYPE						= 'SIZE',
	B_SIZE_T_TYPE					= 'SIZT',
	B_SSIZE_T_TYPE					= 'SSZT',
	B_STRING_LIST_TYPE				= 'STRL',
	B_TIME_TYPE						= 'TIME',
	B_UINT16_TYPE					= 'USHT',
	B_UINT32_TYPE					= 'ULNG',
	B_UINT64_TYPE					= 'ULLG',
	B_UINT8_TYPE					= 'UBYT',
	B_VECTOR_ICON_TYPE				= 'VICN',
	B_XATTR_TYPE					= 'XATR',
	B_NETWORK_ADDRESS_TYPE			= 'NWAD',
	B_MIME_STRING_TYPE				= 'MIMS',
#endif
								case B_STRING_TYPE:
									text = message->FindString(nameFound, j);
									break;
								case B_INT32_TYPE:
								{
									int32 val = message->FindInt32(nameFound, j);
									text.SetToFormat("%d (%#010x)", val, val);
									break;
								}
								case B_POINT_TYPE:
								{
									BPoint val = message->FindPoint(nameFound, j);
									text.SetToFormat("X: %f Y: %f", val.x, val.y);
									break;
								}
								default:
									text.SetTo("TODO: unhandled message content type");
									break;
							}

							BRow* subRow = new BRow();
							subRow->SetField(new BStringField(name), 0);
							subRow->SetField(new BStringField(text), 1);
							fEventList->AddRow(subRow, row);
						}

					}
				}

				break;
			}
			default:
				BWindow::MessageReceived(message);
				break;
		}
	}

private:
	BColumnListView* fEventList;
};


class LoggerApp: public BApplication
{
public:
	LoggerApp()
		: BApplication("application/x-vnd.ml-BeDCApp")
	{
		LoggerWindow* window = new LoggerWindow();
		window->Show();
	}

	void MessageReceived(BMessage* message) override
	{
		switch(message->what) {
			case BEDC_MESSAGE:
				WindowAt(0)->PostMessage(message);
				break;
			default:
				BApplication::MessageReceived(message);
				break;
		}
	}
};


int main(void)
{
	LoggerApp app;
	app.Run();
}
