#include "addsource.hpp"
#include "../modules/addsource.hpp"

#include "../widgets/combobox.hpp"

#include <nanogui/layout.h>
#include <nanogui/label.h>
#include <nanogui/button.h>
#include <nanogui/vscrollpanel.h>
#include <nanogui/tabwidget.h>

#include <loguru.hpp>


using ftl::gui2::AddSourceWindow;

AddSourceWindow::AddSourceWindow(nanogui::Widget* parent, AddCtrl *ctrl) :
		nanogui::Window(parent, ""), ctrl_(ctrl) {

	using namespace nanogui;

	auto t = dynamic_cast<ftl::gui2::Screen*>(screen())->getTheme("window_dark");
	setTheme(t);

	//setFixedWidth(500);
	setFixedSize(Vector2i(500,300));
	setLayout(new nanogui::BoxLayout
				(nanogui::Orientation::Vertical, nanogui::Alignment::Fill, 20, 10));

	setPosition(Vector2i(parent->width()/2.0f - fixedWidth()/2.0f, parent->height()/2.0f - fixedHeight()/2.0f));

	auto close = new nanogui::Button(buttonPanel(), "", ENTYPO_ICON_CROSS);
	close->setTheme(dynamic_cast<ftl::gui2::Screen*>(screen())->getTheme("window_dark"));
	close->setBackgroundColor(theme()->mWindowHeaderGradientBot);
	close->setCallback([this](){ dispose();});

	rebuild();

	new_source_handle_ = ctrl_->feed()->onNewSources([this](int a) {
		LOG(INFO) << "NEW SOURCES";
		UNIQUE_LOCK(mutex_, lk);
		do_rebuild_ = true;
		return true;
	});
}

AddSourceWindow::~AddSourceWindow() {

}

nanogui::Button *AddSourceWindow::_addButton(const std::string &s, nanogui::Widget *parent) {
	using namespace nanogui;

	ftl::URI uri(s);
	int icon = 0;
	switch (uri.getScheme()) {
	case ftl::URI::SCHEME_DEVICE		: icon = ENTYPO_ICON_CAMERA; break;
	case ftl::URI::SCHEME_FILE			: icon = ENTYPO_ICON_FOLDER_VIDEO; break;
	case ftl::URI::SCHEME_FTL			: icon = ENTYPO_ICON_CLOUD; break;
	case ftl::URI::SCHEME_WS			:
	case ftl::URI::SCHEME_TCP			: icon = ENTYPO_ICON_CLASSIC_COMPUTER; break;
	default: break;
	}

	auto *button = new Button(parent, ctrl_->getSourceName(s), icon);
	if (ctrl_->isSourceActive(s)) {
		button->setBackgroundColor(Color(0, 255, 0, 25));
	}

	button->setIconPosition(Button::IconPosition::Left);
	button->setIconExtraScale(1.2);
	button->setFontSize(18);
	button->setTooltip(s);

	button->setCallback([this, uri = s]() {
		ctrl_->add(uri);
		close();
	});

	return button;
}

void AddSourceWindow::rebuild() {
	using namespace nanogui;
	
	auto *title = new Label(this, "Add Source", "sans-bold");
	title->setFontSize(28);

	auto *tabs = new TabWidget(this);

	auto *recent_tab = tabs->createTab("Recent");
	recent_tab->setLayout(new nanogui::BoxLayout
				(nanogui::Orientation::Vertical, nanogui::Alignment::Fill, 0, 0));
	VScrollPanel *vscroll = new VScrollPanel(recent_tab);
	vscroll->setFixedHeight(200);
	Widget *recentscroll = new Widget(vscroll);
	recentscroll->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill, 10, 4));

	Button *button;

	auto srcs = ctrl_->getRecent();

	for (auto &s : srcs) {
		_addButton(s.uri, recentscroll);
	}

	auto *group_tab = tabs->createTab("Groups");
	group_tab->setLayout(new nanogui::BoxLayout
				(nanogui::Orientation::Vertical, nanogui::Alignment::Fill, 0, 0));
	vscroll = new VScrollPanel(group_tab);
	vscroll->setFixedHeight(150);
	Widget *groupscroll = new Widget(vscroll);
	groupscroll->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill, 10, 4));

	auto groups = ctrl_->getGroups();

	for (auto &s : groups) {
		_addButton(s, groupscroll);
	}

	auto *dev_tab = tabs->createTab("Devices");
	dev_tab->setLayout(new nanogui::BoxLayout
				(nanogui::Orientation::Vertical, nanogui::Alignment::Fill, 0, 0));
	vscroll = new VScrollPanel(dev_tab);
	vscroll->setFixedHeight(150);
	Widget *devscroll = new Widget(vscroll);
	devscroll->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill, 10, 4));

	auto devsrcs = ctrl_->getDeviceSources();

	for (auto &s : devsrcs) {
		_addButton(s, devscroll);
	}

	auto *host_tab = tabs->createTab("Hosts");
	host_tab->setLayout(new nanogui::BoxLayout
				(nanogui::Orientation::Vertical, nanogui::Alignment::Fill, 0, 0));
	vscroll = new VScrollPanel(host_tab);
	vscroll->setFixedHeight(150);
	Widget *hostscroll = new Widget(vscroll);
	hostscroll->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill, 10, 4));

	button = new Button(hostscroll, "Add Host", ENTYPO_ICON_PLUS);
	button->setIconPosition(Button::IconPosition::Left);
	button->setIconExtraScale(1.2);
	button->setFontSize(18);
	button->setTooltip("Manually add a new connection URI");
	button->setCallback([this]() {

	});

	auto hostsrcs = ctrl_->getHosts();

	for (auto &s : hostsrcs) {
		_addButton(s, hostscroll);
	}

	auto *stream_tab = tabs->createTab("Streams");
	stream_tab->setLayout(new nanogui::BoxLayout
				(nanogui::Orientation::Vertical, nanogui::Alignment::Fill, 0, 0));
	vscroll = new VScrollPanel(stream_tab);
	vscroll->setFixedHeight(150);
	Widget *streamscroll = new Widget(vscroll);
	streamscroll->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill, 10, 4));

	auto streamsrcs = ctrl_->getNetSources();

	for (auto &s : streamsrcs) {
		_addButton(s, streamscroll);
	}

	auto *file_tab = tabs->createTab("Files");
	file_tab->setLayout(new nanogui::BoxLayout
				(nanogui::Orientation::Vertical, nanogui::Alignment::Fill, 0, 0));
	vscroll = new VScrollPanel(file_tab);
	vscroll->setFixedHeight(150);
	Widget *filescroll = new Widget(vscroll);
	filescroll->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill, 10, 4));

	button = new Button(filescroll, "Open", ENTYPO_ICON_PLUS);
	button->setIconPosition(Button::IconPosition::Left);
	button->setIconExtraScale(1.2);
	button->setFontSize(18);
	button->setTooltip("Open FTL File");
	button->setCallback([this]() {
		try {
			std::string filename = file_dialog({ {"ftl", "FTL Captures"} }, false);
			if (filename.size() > 0 && filename[0] == '/') {
				filename = std::string("file://") + filename;
			} else {
				filename = std::string("file:///") + filename;
			}
#ifdef WIN32
			auto p = filename.find_first_of('\\');
			while (p != std::string::npos) {
				filename[p] = '/';
				p = filename.find_first_of('\\');
			}
#endif
			ctrl_->add(filename);
		} catch (const std::exception &e) {
			LOG(ERROR) << "File load exception: " << e.what();
		}
		close();
	});

	auto filesrcs = ctrl_->getFileSources();

	for (auto &s : filesrcs) {
		_addButton(s, filescroll);
	}


	tabs->setActiveTab(0);


	/*button = new Button(devicebuttons, "Camera(s)");
	button->setCallback([this]() { ctrl_->add("device:camera"); close(); });
	button = new Button(devicebuttons, "Realsense");
	button->setCallback([this]() { ctrl_->add("device:realsense"); close(); });
	button = new Button(devicebuttons, "Screen");
	button->setCallback([this]() { ctrl_->add("device:screen"); close(); });
	button = new Button(devicebuttons, "3D Camera");
	button->setCallback([this]() { ctrl_->add("device:render"); close(); });
	button = new Button(devicebuttons, "OpenVR");
	button->setCallback([this]() { ctrl_->add("device:openvr"); close(); });*/

	/*new Label(this, "Network Sources", "sans-bold");

	auto *netbuttons = new Widget(this);
	netbuttons->setLayout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 0, 4));
	auto netsrcs = ctrl_->getNetSources();

	for (auto &s : netsrcs) {
		button = new Button(netbuttons, ctrl_->getSourceName(s));
		if (ctrl_->isSourceActive(s)) {
			button->setBackgroundColor(Color(0, 255, 0, 25));
		}

		button->setCallback([this, s]() {
			ctrl_->add(s);
			close();
		});
	}*/

	//new Label(this, "Files", "sans-bold");

	//auto *filebuttons = new Widget(this);
	//filebuttons->setLayout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 0, 4));
	

	/*auto filesrcs = ctrl_->getFileSources();

	for (auto &s : filesrcs) {
		button = new Button(filebuttons, ctrl_->getSourceName(s));
		if (ctrl_->isSourceActive(s)) {
			button->setBackgroundColor(Color(0, 255, 0, 25));
		}

		button->setCallback([this, s]() {
			ctrl_->add(s);
			close();
		});
	}*/
}

void AddSourceWindow::close() {
	setVisible(false);
	dispose();
}

void AddSourceWindow::draw(NVGcontext *ctx) {
	{
		UNIQUE_LOCK(mutex_, lk);
		if (do_rebuild_) {
			do_rebuild_ = false;
			// Note the 1, first widget is the title bar buttons
			while(childCount() > 1) { removeChild(childCount()-1); }
			rebuild();
			screen()->performLayout();
		}
	}

	nanogui::Window::draw(ctx);
}