/*
 * Copyright (c) 2008 Hypertriton, Inc. 
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include 
#include "file_selector.h"
AG_FileSelector *
AG_FileSelectorNew(void *parent, Uint flags, const char *label)
{
	AG_FileSelector *fs;
	fs = Malloc(sizeof(AG_FileSelector));
	AG_ObjectInit(fs, &agFileSelectorClass);
	fs->flags |= flags;
	if (label != NULL) {
		AG_TextboxSetLabel(fs->tbox, "%s", label);
	}
	if (flags & AG_FILE_SELECTOR_HFILL) { AG_ExpandHoriz(fs); }
	if (flags & AG_FILE_SELECTOR_VFILL) { AG_ExpandVert(fs); }
	
	AG_ObjectAttach(parent, fs);
	return (fs);
}
static void
Collapse(AG_FileSelector *fs)
{
	if (fs->panel == NULL) {
		return;
	}
	fs->wSaved = WIDTH(fs->panel);
	fs->hSaved = HEIGHT(fs->panel);
	AG_WindowHide(fs->panel);
	AG_ObjectDetach(fs->filedlg);
	AG_ViewDetach(fs->panel);
	fs->panel = NULL;
	AG_SetInt(fs->button, "state", 0);
}
static void
ModalClose(AG_Event *event)
{
	AG_FileSelector *fs = AG_PTR(1);
	if (fs->panel != NULL)
		Collapse(fs);
}
static void
Expand(AG_Event *event)
{
	AG_FileSelector *fs = AG_PTR(1);
	int expand = AG_INT(2);
	AG_SizeReq rFileDlg;
	int x, y, w, h;
	if (expand) {						/* Expand */
		fs->panel = AG_WindowNew(AG_WINDOW_MODAL|AG_WINDOW_NOTITLE);
		AG_WindowSetPadding(fs->panel, 0, 0, 0, 0);
		AG_ObjectAttach(fs->panel, fs->filedlg);
		
		if (fs->wSaved > 0) {
			w = fs->wSaved;
			h = fs->hSaved;
		} else {
			AG_WidgetSizeReq(fs->filedlg, &rFileDlg);
			w = rFileDlg.w + fs->panel->wBorderSide*2;
			h = rFileDlg.h + fs->panel->wBorderBot;
 		}
		x = WIDGET(fs)->rView.x2 - w;
		y = WIDGET(fs)->rView.y1;
		if (x+w > agView->w) { w = agView->w - x; }
		if (y+h > agView->h) { h = agView->h - y; }
		if (w < 4 || h < 4) {
			Collapse(fs);
			return;
		}
		AG_SetEvent(fs->panel, "window-modal-close",
		    ModalClose, "%p", fs);
		AG_WindowSetGeometry(fs->panel, x, y, w, h);
		AG_WindowShow(fs->panel);
	} else {
		Collapse(fs);
	}
}
static void
SetDirectoryAndFile(AG_FileSelector *fs, const char *pPath)
{
	char path[AG_FILENAME_MAX], *file;
	
	Strlcpy(path, pPath, sizeof(path));
	if ((file = strrchr(path, AG_PATHSEPCHAR)) != NULL) {
		AG_FileDlgSetFilename(fs->filedlg, file);
		*file = '\0';
		AG_FileDlgSetDirectory(fs->filedlg, path);
	}
}
static void
SetDirectory(AG_FileSelector *fs, const char *pPath)
{
	char path[AG_FILENAME_MAX];
	
	Strlcpy(path, pPath, sizeof(path));
	AG_FileDlgSetDirectory(fs->filedlg, path);
}
void
AG_FileSelectorSetFile(AG_FileSelector *fs, const char *path)
{
	AG_ObjectLock(fs->filedlg);
	SetDirectoryAndFile(fs, path);
	AG_TextboxSetString(fs->tbox, path);
	AG_ObjectUnlock(fs->filedlg);
}
void
AG_FileSelectorSetDirectory(AG_FileSelector *fs, const char *path)
{
	char dir[AG_PATHNAME_MAX];
	Strlcpy(dir, path, sizeof(dir));
	if (dir[0] != '\0' && dir[strlen(dir)-1] != AG_PATHSEPCHAR) {
		dir[strlen(dir)-1] = AG_PATHSEPCHAR;
	}
	AG_ObjectLock(fs->filedlg);
	SetDirectory(fs, dir);
	AG_TextboxSetString(fs->tbox, dir);
	AG_ObjectUnlock(fs->filedlg);
}
static void
FileChosen(AG_Event *event)
{
	AG_FileSelector *fs = AG_PTR(1);
	char *path = AG_STRING(2);
	AG_TextboxSetString(fs->tbox, path);
	AG_PostEvent(NULL, fs, "file-chosen", "%s", path);
	Collapse(fs);
}
static void
Return(AG_Event *event)
{
	char path[AG_TEXTBOX_STRING_MAX];
	AG_Textbox *tbox = AG_SELF();
	AG_FileSelector *fs = AG_PTR(1);
	
	AG_ObjectLock(fs->filedlg);
	AG_TextboxCopyString(tbox, path, sizeof(path));
	/* XXX TODO: Check access, AG_FILE_SELECTOR_ANY_FILE */
	SetDirectoryAndFile(fs, path);
	AG_PostEvent(NULL, fs, "file-chosen", "%s", path);
	AG_ObjectUnlock(fs->filedlg);
}
static void
Init(void *obj)
{
	AG_FileSelector *fs = obj;
	fs->flags = 0;
	fs->panel = NULL;
	fs->wSaved = 0;
	fs->hSaved = 0;
	
	fs->tbox = AG_TextboxNew(fs, AG_TEXTBOX_COMBO, NULL);
	fs->button = AG_ButtonNew(fs, AG_BUTTON_STICKY, _("Browse..."));
	AG_ButtonSetPadding(fs->button, 1,1,1,1);
	AG_WidgetSetFocusable(fs->button, 0);
	fs->filedlg = Malloc(sizeof(AG_FileDlg));
	AG_ObjectInit(fs->filedlg, &agFileDlgClass);
	AG_Expand(fs->filedlg);
	
	AG_SetEvent(fs->button, "button-pushed", Expand, "%p", fs);
	AG_SetEvent(fs->filedlg, "file-chosen", FileChosen, "%p", fs);
	AG_SetEvent(fs->tbox, "textbox-return", Return, "%p", fs);
}
static void
Destroy(void *p)
{
	AG_FileSelector *fs = p;
	if (fs ->panel != NULL) {
		AG_WindowHide(fs->panel);
		AG_ObjectDetach(fs->filedlg);
		AG_ViewDetach(fs->panel);
	}
	AG_ObjectDestroy(fs->filedlg);
}
static void
Draw(void *obj)
{
	AG_Widget *chld;
	WIDGET_FOREACH_CHILD(chld, obj)
		AG_WidgetDraw(chld);
}
static void
SizeRequest(void *obj, AG_SizeReq *r)
{
	AG_FileSelector *fs = obj;
	AG_SizeReq rChld;
	AG_WidgetSizeReq(fs->tbox, &rChld);
	r->w = rChld.w;
	r->h = rChld.h;
	AG_WidgetSizeReq(fs->button, &rChld);
	r->w += rChld.w;
	if (r->h < rChld.h) { r->h = rChld.h; }
}
static int
SizeAllocate(void *obj, const AG_SizeAlloc *a)
{
	AG_FileSelector *fs = obj;
	AG_SizeReq rBtn;
	AG_SizeAlloc aChld;
	AG_WidgetSizeReq(fs->button, &rBtn);
	if (a->w < rBtn.w) {
		return (-1);
	}
	aChld.x = 0;
	aChld.y = 0;
	aChld.w = a->w - rBtn.w - 1;
	aChld.h = a->h;
	AG_WidgetSizeAlloc(fs->tbox, &aChld);
	aChld.x = aChld.w + 1;
	aChld.w = rBtn.w;
	AG_WidgetSizeAlloc(fs->button, &aChld);
	return (0);
}
AG_WidgetClass agFileSelectorClass = {
	{
		"Agar(Widget:FileSelector)",
		sizeof(AG_FileSelector),
		{ 0,0 },
		Init,
		NULL,			/* free */
		Destroy,
		NULL,			/* load */
		NULL,			/* save */
		NULL			/* edit */
	},
	Draw,
	SizeRequest,
	SizeAllocate
};