# TabWidget.nas - widget with a tabs bar and a content area which always displays
# exactly one of its tabs

# SPDX-FileCopyrightText: (C) 2022 Frederic Croix <thefgfseagle@gmail.com>
# SPDX-License-Identifier: GPL-2.0-or-later

# Usage  example
# var window = canvas.Window.new([300, 300], "dialog");
# var myCanvas = window.createCanvas().set("background", canvas.style.getColor("bg_color"));
# var root = myCanvas.createGroup();
# var vbox = canvas.VBoxLayout.new();
# myCanvas.setLayout(vbox);
# 
# var tabs = canvas.gui.widgets.TabWidget.new(root, canvas.style, {});
# var tabsContent = tabs.getContent();
# vbox.addItem(tabs);
# 
# var tab1 = canvas.VBoxLayout.new();
# var image1 = canvas.gui.widgets.Label.new(tabsContent, canvas.style, {})
#                 .setImage("Textures/Splash1.png")
#                 .setFixedSize(128, 128);
# tab1.addItem(image1);
# var text1 = canvas.gui.widgets.Label.new(tabsContent, canvas.style, {})
#                 .setText("Texture 1");
# tab1.addItem(text1);
# tabs.addTab("tab1", "Texture 1", tab1);
# 
# var tab2 = canvas.VBoxLayout.new();
# var image2 = canvas.gui.widgets.Label.new(tabsContent, canvas.style, {})
#                 .setImage("Textures/Splash2.png")
#                 .setFixedSize(128, 128);
# tab2.addItem(image2);
# var text2 = canvas.gui.widgets.Label.new(tabsContent, canvas.style, {})
#                 .setText("Texture 2");
# tab2.addItem(text2);
# tabs.addTab("tab2", "Texture 2", tab2);
# 
# var tab3 = canvas.VBoxLayout.new();
# var image3 = canvas.gui.widgets.Label.new(tabsContent, canvas.style, {})
#                 .setImage("Textures/Splash3.png")
#                 .setFixedSize(128, 128);
# tab3.addItem(image3);
# var text3 = canvas.gui.widgets.Label.new(tabsContent, canvas.style, {})
#                 .setText("Texture 3");
# tab3.addItem(text3);
# tabs.addTab("tab3", "Texture 3", tab3);

gui.widgets.TabWidgetTabButton = {
	new: func(parent, style, cfg) {
		var cfg = Config.new(cfg);
		var m = gui.Widget.new(gui.widgets.TabWidgetTabButton);
		m._focus_policy = m.StrongFocus;
		m._selected = 0;

		m._setView(style.createWidget(parent, "tab-widget-tab-button", cfg));

		return m;
	},
	setText: func(text) {
		me._view.setText(me, text);
		
		return me;
	},
	setSelected: func(selected = 1) {
		if (me._selected == selected) {
			return me;
		}

		me._selected = selected;
		me._trigger("toggled", {selected: selected});
		me._onStateChange();
		me._view.update(me);
		return me;
	},
	_setView: func(view) {
		call(gui.Widget._setView, [view], me);

		var el = view._root;
		#el.addEventListener("mousedown", func me.dragStart());
		#el.addEventListener("mouseup", func me.dragStop());
		el.addEventListener("click", func me.setSelected());

		el.addEventListener("drag", func(e) { e.stopPropagation() });
		#el.addEventListener("drag", me.drag);
	}
};

gui.widgets.TabWidget = {
	new: func(parent, style, cfg) {
		var m = gui.Widget.new(gui.widgets.TabWidget);
		m._cfg = Config.new(cfg);
		m._focus_policy = m.NoFocus;
		m._setView(style.createWidget(parent, "tab-widget", m._cfg));
		m._layout = VBoxLayout.new();
		m._layout.setCanvas(m._view._root.getCanvas());
		m._tabBar = HBoxLayout.new();
		m._layout.addItem(m._tabBar);
		m._currentTab = nil;
		m._currentTabId = nil;
		m._tabs = {};
		m._tabButtons = {};
		
		m.setLayoutMinimumSize([50, 30]);
		m.setLayoutSizeHint([100, 30]);
		
		return m;
	},
	
	getContent: func {
		return me._view.content;
	},
	
	hasTab: func(id) {
		return me._tabs[id] != nil;
	},
	
	getTab: func(id) {
		if (!me.hasTab(id)) {
			die("tab with id '" ~ id ~ "' does not exist");
		}
		
		return me._tabs[id];
	},
	
	addTab: func(id, label, widget) {
		if (me.hasTab(id)) {
			die("cannot add multiple tabs with the same id: " ~ id);
		}
		
		me._tabButtons[id] = gui.widgets.TabWidgetTabButton.new(me._view.tabBar, canvas.style, {})
								.setText(label)
								.listen("toggled", func (e) {
									if (e.detail.selected and id != me._currentTabId) {
										me.setCurrentTab(id);
									}
								});
		
		me._tabBar.addItem(me._tabButtons[id]);
		me._tabs[id] = widget;
		me._layout.addItem(widget);
		me.setCurrentTab(keys(me._tabs)[0]);
		
		return me;
	},
	
	removeTab: func(id) {
		if (!me.hasTab(id)) {
			die("tab with id '" ~ id ~ "' does not exist");
		}
		
		me._tabs[id].setVisible(0);
		me._layout.removeItem(me._tabs[id]);
		delete(me._tabs, id);
		me._tabBar.removeItem(me._tabButtons[id]);
		delete(me._tabButtons, id);
		if (size(keys(me._tabs)) > 0) {
			me.setCurrentTab(keys(me._tabs)[-1]);
		}
		
		return me;
	},
	
	setCurrentTab: func(id) {
		if (!me.hasTab(id)) {
			die("tab with id '" ~ id ~ "' does not exist");
		}
		
		if (me._currentTabId) {
			me._tabButtons[me._currentTabId].setSelected(0);
		}
		me._tabButtons[id].setSelected();
		foreach (var tabid; keys(me._tabs)) {
			me._tabs[tabid].setVisible(0);
		}
		me._tabs[id].setVisible(1);
		me._currentTabId = id;
		me._currentTab = me._tabs[id];
		
		return me.update();
	},
	
	setSize: func {
		if (size(arg) == 1) {
			var arg = arg[0];
		}
		var (x, y) = arg;
		me._size = [x, y];
		return me.update();
	},
	
	# Needs to be called when the size of the content changes.
	update: func() {
		if(me._layout.getParent() == nil) {
			me._layout.setParent(me);
		}
		
		me._tabBar.setGeometry([0, 0, me._size[0], me._view.tabBarHeight]);
		if (me._currentTab) {
			me._currentTab.setGeometry([0, me._view.tabBarHeight, me._size[0], me._size[1] - me._view.tabBarHeight]);
		}
		me._view.setSize(me, me._size[0], me._size[1]);
		
		me._view.update(me);

		return me;
	},
};