// Copyright (C) 2018-2024, Tellusim Technologies Inc. All rights reserved
// https://tellusim.com/

#include <platform/TellusimWindow.h>

#include "../include/TellusimControlModal.h"

/*
 */
namespace Tellusim {
	
	/*
	 */
	ControlModal::ControlModal(Control *parent, Flags flags) : ControlModal(parent, 1, nullptr, nullptr, flags) { }
	ControlModal::ControlModal(Control *parent, const char *title, Flags flags) : ControlModal(parent, 1, title, nullptr, flags) { }
	ControlModal::ControlModal(Control *parent, const String &title, Flags flags) : ControlModal(parent, 1, title.get(), nullptr, flags) { }
	ControlModal::ControlModal(Control *parent, uint32_t columns, const char *title, Flags flags) : ControlModal(parent, columns, title, nullptr, flags) { }
	ControlModal::ControlModal(Control *parent, uint32_t columns, const String &title, Flags flags) : ControlModal(parent, columns, title.get(), nullptr, flags) { }
	ControlModal::ControlModal(Control *parent, const char *title, const char *message, Flags flags) : ControlModal(parent, 1, title, message, flags) { }
	ControlModal::ControlModal(Control *parent, const char *title, const String &message, Flags flags) : ControlModal(parent, 1, title, message.get(), flags) { }
	ControlModal::ControlModal(Control *parent, const String &title, const String &message, Flags flags) : ControlModal(parent, 1, title.get(), message.get(), flags) { }
	ControlModal::ControlModal(Control *parent, uint32_t columns, const String &title, const String &message, Flags flags) : ControlModal(parent, columns, title.get(), message.get(), flags) { }
	
	ControlModal::ControlModal(Control *parent, uint32_t columns, const char *title, const char *message, Flags flags) : ControlBase(parent) {
		
		// control align
		setAlign(AlignOverlap);
		
		// create control
		create(columns, title, message, flags);
	}
	
	ControlModal::~ControlModal() {
		
		// release self
		Control parent = getParent();
		if(parent) parent.removeChild(*this);
		
		// release controls
		parent = modal_panel.getParent();
		if(parent) parent.removeChild(modal_panel);
	}
	
	/*
	 */
	void ControlModal::create(uint32_t columns, const char *title, const char *message, Flags flags) {
		
		// parent control
		Control parent = getParent();
		if(parent) {
			Control panel = parent.getPanel();
			if(panel) parent = panel;
		}
		
		// root control
		ControlRoot root = getRoot();
		uint32_t font_size = root.getFontSize() + 4;
		
		// modal panel
		modal_panel = ControlPanel(&parent, 1, 0.0f, 12.0f);
		modal_panel.setAlign(AlignCenter | AlignOverlap);
		modal_panel.setColor(Color(0.12f, 1.0f));
		modal_panel.setCallback(true);
		
		// title text
		title_text = ControlText(&modal_panel);
		title_text.setAlign(AlignCenterX);
		title_text.setFontSize(font_size);
		
		// message text
		message_text = ControlText(&modal_panel);
		message_text.setAlign(AlignCenterX);
		message_text.setMargin(0.0f, font_size / 4.0f);
		message_text.setFontSize(font_size);
		
		// modal grid
		modal_grid = ControlGrid(&modal_panel, columns, 4.0f, 4.0f);
		modal_grid.setAlign(AlignExpand);
		
		// buttons grid
		ControlGrid grid(&modal_panel, 4, 4.0f, 4.0f);
		grid.setAlign(AlignRight);
		
		// button parameters
		const bool buttons_ret[] = { true, false, true, false, false };
		const char *buttons_text[] = { "Yes", "No", "Ok", "Cancel", "Close" };
		TS_STATIC_ASSERT(TS_COUNTOF(buttons_ret) == NumResults);
		TS_STATIC_ASSERT(TS_COUNTOF(buttons_text) == NumResults);
		
		// create buttons
		for(uint32_t i = 0; i < NumResults; i++) {
			if(!(flags & (1 << i))) continue;
			
			// create button
			ControlButton button = ControlButton(&grid, buttons_text[i]);
			button.setButtonRadius(getButtonRadius());
			button.setSize(96.0f, 18.0f);
			button.setAlign(AlignRight);
			buttons[i] = button;
			
			// button keys
			if(ret_result == NumResults && buttons_ret[i]) ret_result = (Result)i;
			if(esc_result == NumResults && !buttons_ret[i]) esc_result = (Result)i;
			
			// clicked callback
			button.setClickedCallback(makeFunction([this](ControlButton button, Result ret) {
				result = ret;
			}, ControlButton::null, (Result)i));
		}
		
		// default parameters
		setSize(384.0f, 0.0f);
		setRadius(24.0f);
		setTitle(title);
		setMessage(message);
		
		ControlBase::create();
	}
	
	/*
	 */
	void ControlModal::setSize(float32_t width, float32_t height) {
		modal_panel.setSize(width, height);
	}
	
	void ControlModal::setRadius(float32_t radius) {
		modal_panel.setRadius(radius);
		modal_panel.setMargin(radius);
	}
	
	void ControlModal::setColor(const Color &color) {
		modal_panel.setColor(color);
	}
	
	void ControlModal::setStrokeStyle(const StrokeStyle &style) {
		modal_panel.setStrokeStyle(style);
	}
	
	void ControlModal::setGradientStyle(const GradientStyle &style) {
		modal_panel.setMode(CanvasElement::ModeGradient);
		modal_panel.setGradientStyle(style);
	}
	
	/*
	 */
	void ControlModal::setTitle(const char *text) {
		title_text.setText(text);
		title_text.setEnabled((bool)title_text.getText());
	}
	
	void ControlModal::setTitle(const String &text) {
		title_text.setText(text);
		title_text.setEnabled((bool)title_text.getText());
	}
	
	/*
	 */
	void ControlModal::setMessage(const char *text) {
		message_text.setText(text);
		message_text.setEnabled((bool)message_text.getText());
	}
	
	void ControlModal::setMessage(const String &text) {
		message_text.setText(text);
		message_text.setEnabled((bool)message_text.getText());
	}
	
	/*
	 */
	void ControlModal::setButtonRadius(float32_t radius) {
		button_radius = radius;
	}
	
	/*
	 */
	void ControlModal::update_enabled(bool enabled) {
		enabled &= isEnabled();
		if(modal_panel.isEnabled() != enabled) {
			modal_panel.setEnabled(enabled);
		}
		ControlBase::update_enabled(enabled);
	}
	
	/*
	 */
	ControlModal::Result ControlModal::run(Window &window) {
		
		// set modal control
		ControlRoot root = getRoot();
		Control modal = root.getModalControl();
		root.setModalControl(modal_panel);
		
		// clear result
		result = NumResults;
		
		// run main loop
		while(result == NumResults) {
			Window::MainLoopCallback main_loop = window.getMainLoopCallback();
			if(ret_result != NumResults && window.getKeyboardKey(Window::KeyReturn, true)) result = ret_result;
			if(esc_result != NumResults && window.getKeyboardKey(Window::KeyEsc, true)) result = esc_result;
			if(main_loop) main_loop();
			else break;
		}
		
		// restore modal control
		if(modal) root.setModalControl(modal);
		else root.clearModalControl();
		
		return result;
	}
}
