/* -----------------------------------------------------------------------------
 *
 * Giada - Your Hardcore Loopmachine
 *
 * -----------------------------------------------------------------------------
 *
 * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
 *
 * This file is part of Giada - Your Hardcore Loopmachine.
 *
 * Giada - Your Hardcore Loopmachine is free software: you can
 * redistribute it and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * Giada - Your Hardcore Loopmachine is distributed in the hope that it
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Giada - Your Hardcore Loopmachine. If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * -------------------------------------------------------------------------- */

#include "browser.h"
#include "basics/boxtypes.h"
#include "core/const.h"
#include "gui/dialogs/browser/browserBase.h"
#include "utils/fs.h"
#include "utils/string.h"

namespace giada
{
namespace v
{
geBrowser::geBrowser(int x, int y, int w, int h)
: Fl_File_Browser(x, y, w, h)
, m_showHiddenFiles(false)
{
	box(G_CUSTOM_BORDER_BOX);
	textsize(G_GUI_FONT_SIZE_BASE);
	textcolor(G_COLOR_LIGHT_2);
	selection_color(G_COLOR_GREY_4);
	color(G_COLOR_GREY_2);
	type(FL_SELECT_BROWSER);

	this->scrollbar.color(G_COLOR_GREY_2);
	this->scrollbar.selection_color(G_COLOR_GREY_4);
	this->scrollbar.labelcolor(G_COLOR_LIGHT_1);
	this->scrollbar.slider(G_CUSTOM_BORDER_BOX);

	this->hscrollbar.color(G_COLOR_GREY_2);
	this->hscrollbar.selection_color(G_COLOR_GREY_4);
	this->hscrollbar.labelcolor(G_COLOR_LIGHT_1);
	this->hscrollbar.slider(G_CUSTOM_BORDER_BOX);

	take_focus(); // let it have focus on startup
}

/* -------------------------------------------------------------------------- */

void geBrowser::toggleHiddenFiles()
{
	m_showHiddenFiles = !m_showHiddenFiles;
	loadDir(m_currentDir);
}

/* -------------------------------------------------------------------------- */

void geBrowser::loadDir(const std::string& dir)
{
	m_currentDir = dir;
	load(m_currentDir.c_str());

	/* Clean up unwanted elements. Hide "../" first, it just screws up things.
	Also remove hidden files, if requested. */

	for (int i = size(); i >= 0; i--)
	{
		if (text(i) == nullptr)
			continue;
		if (strcmp(text(i), "../") == 0 || (!m_showHiddenFiles && strncmp(text(i), ".", 1) == 0))
			remove(i);
	}
}

/* -------------------------------------------------------------------------- */

int geBrowser::handle(int e)
{
	int ret = Fl_File_Browser::handle(e);
	switch (e)
	{
	case FL_FOCUS:
	case FL_UNFOCUS:
		ret = 1; // enables receiving Keyboard events
		break;
	case FL_KEYDOWN: // keyboard
		if (Fl::event_key(FL_Down))
			select(value() + 1);
		else if (Fl::event_key(FL_Up))
			select(value() - 1);
		else if (Fl::event_key(FL_Enter))
			static_cast<v::gdBrowserBase*>(parent())->fireCallback();
		ret = 1;
		break;
	case FL_PUSH:                   // mouse
		if (Fl::event_clicks() > 0) // double click
			static_cast<v::gdBrowserBase*>(parent())->fireCallback();
		ret = 1;
		break;
	case FL_RELEASE: // mouse
		/* nasty trick to keep the selection on mouse release */
		if (value() > 1)
		{
			select(value() - 1);
			select(value() + 1);
		}
		else
		{
			select(value() + 1);
			select(value() - 1);
		}
		ret = 1;
		break;
	}
	return ret;
}

/* -------------------------------------------------------------------------- */

std::string geBrowser::getCurrentDir()
{
	return normalize(u::fs::getRealPath(m_currentDir));
}

/* -------------------------------------------------------------------------- */

std::string geBrowser::getSelectedItem(bool fullPath)
{
	if (!fullPath) // no full path requested? return the selected text
		return normalize(text(value()));
	else if (value() == 0) // no rows selected? return current directory
		return normalize(m_currentDir);
	else
	{
#ifdef G_OS_WINDOWS
		std::string sep = m_currentDir != "" ? G_SLASH_STR : "";
#else
		std::string sep = G_SLASH_STR;
#endif
		return normalize(u::fs::getRealPath(m_currentDir + sep + normalize(text(value()))));
	}
}

/* -------------------------------------------------------------------------- */

void geBrowser::preselect(int pos, int line)
{
	position(pos);
	select(line);
}

/* -------------------------------------------------------------------------- */

std::string geBrowser::normalize(const std::string& s)
{
	std::string out = s;

	/* If std::string ends with G_SLASH, remove it. Don't do it if is the root dir, 
	that is '/' on Unix or '[x]:\' on Windows. */

	//if (out.back() == G_SLASH && out.length() > 1)
	if (out.back() == G_SLASH && !u::fs::isRootDir(s))
		out = out.substr(0, out.size() - 1);
	return out;
}
} // namespace v
} // namespace giada