/** \file linknoteui.c
 * View for the text note
 */

/*  XTrkCad - Model Railroad CAD
 *  Copyright (C) 2018 Martin Fischer
 *
 *  This program 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "custom.h"
#include "dynstring.h"
#include "misc.h"
#include "note.h"
#include "param.h"
#include "include/stringxtc.h"
#include "track.h"
#include "validator.h"
#include "cundo.h"

#define DEFAULTLINKURL "http://www.xtrkcad.org/"
#define DEFAULTLINKTITLE "The XTrackCAD Homepage"
struct {
	coOrd pos;
	int layer;
	track_p trk;
	char title[TITLEMAXIMUMLENGTH];
	char url[URLMAXIMUMLENGTH];
} linkNoteData;

static void NoteLinkBrowse(void *junk);
static void NoteLinkOpen(char *url );

static paramFloatRange_t noRangeCheck = { 0.0, 0.0, 80, PDO_NORANGECHECK_HIGH | PDO_NORANGECHECK_LOW };
static paramData_t linkNotePLs[] = {
#define I_ORIGX (0)
	/*0*/ { PD_FLOAT, &linkNoteData.pos.x, "origx", PDO_DIM|PDO_NOPREF, &noRangeCheck, N_("Position X") },
#define I_ORIGY (1)
	/*1*/ { PD_FLOAT, &linkNoteData.pos.y, "origy", PDO_DIM|PDO_NOPREF, &noRangeCheck, N_("Position Y") },
#define I_LAYER (2)
	/*2*/ { PD_DROPLIST, &linkNoteData.layer, "layer", PDO_NOPREF, I2VP(150), "Layer", 0 },
#define I_TITLE (3)
	/*3*/ { PD_STRING, &linkNoteData.title, "title", PDO_NOPREF | PDO_NOTBLANK, I2VP(200), N_("Title"), 0, 0, sizeof(linkNoteData.title ) },
#define I_URL (4)
	/*4*/ { PD_STRING, &linkNoteData.url, "name", PDO_NOPREF | PDO_NOTBLANK, I2VP(200), N_("URL"), 0, 0, sizeof(linkNoteData.url ) },
#define I_OPEN (5)
	/*5*/{ PD_BUTTON, NoteLinkBrowse, "openlink", PDO_DLGHORZ, NULL, N_("Open...") },
};

static paramGroup_t linkNotePG = { "linkNote", 0, linkNotePLs, COUNT( linkNotePLs ) };
static wWin_p linkNoteW;

BOOL_T
IsLinkNote(track_p trk)
{
	struct extraDataNote_t * xx = GET_EXTRA_DATA( trk, T_NOTE, extraDataNote_t );

	return(xx->op == OP_NOTELINK);
}


/**
 * Callback for Open URL button
 *
 * \param junk IN ignored
 */
static void NoteLinkBrowse(void *junk)
{
	NoteLinkOpen(linkNoteData.url);
}

/**
 * Open the URL in the external default browser
 *
 * \param url IN url to open
 */
static void NoteLinkOpen(char *url)
{
	wOpenFileExternal(url);
}

static void
LinkDlgUpdate(
        paramGroup_p pg,
        int inx,
        void * valueP)
{
	switch (inx) {
	case I_URL:
		if ( ! IsValidURL( linkNoteData.url ) ) {
			printf( "URL %s is invalid\n", linkNoteData.url );
			paramData_p p = &linkNotePLs[I_URL];
			p->bInvalid = TRUE;
			wWinPix_t h = wControlGetHeight(p->control);
			wControlSetBalloon( p->control, 0, -h*3/4, "URL is invalid" );
			ParamHilite( p->group->win, p->control, TRUE );
		}
		break;
	case I_ORIGX:
	case I_ORIGY:
		// TODO: Redraw bitmap at new location
		break;
	default:
		break;
	}
}


/**
 * Handle OK button: make sure the entered URL is syntactically valid, update
 * the layout and close the dialog
 *
 * \param junk
 */

static void
LinkEditOK(void *junk)
{
	track_p trk = linkNoteData.trk;
	if ( trk == NULL ) {
		// new note
		trk = NewNote( -1, linkNoteData.pos, OP_NOTELINK );
	} else {
		if ( ! descUndoStarted ) {
			UndoStart( _("Update Link Note"), "Update Link Note" );
			descUndoStarted = TRUE;
		}
		UndoModify( trk );
	}
	struct extraDataNote_t * xx = GET_EXTRA_DATA( trk, T_NOTE, extraDataNote_t );
	xx->pos = linkNoteData.pos;
	SetTrkLayer( trk, linkNoteData.layer );
	UndoDeferFree( xx->noteData.linkData.title );
	UndoDeferFree( xx->noteData.linkData.url );
	xx->noteData.linkData.title = MyStrdup( linkNoteData.title );
	xx->noteData.linkData.url = MyStrdup( linkNoteData.url );
	SetBoundingBox( trk, xx->pos, xx->pos );
	DrawNewTrack( trk );
	wHide(linkNoteW);
	ResetIfNotSticky();
	SetFileChanged();
}


static void
CreateEditLinkDialog(char *title)
{

	// create the dialog if necessary
	if (!linkNoteW) {
		ParamRegister(&linkNotePG);
		linkNoteW = ParamCreateDialog(&linkNotePG,
		                              "",
		                              _("Done"), LinkEditOK,
		                              ParamCancel_Current, TRUE, NULL,
		                              F_BLOCK,
		                              LinkDlgUpdate);
	}

	wWinSetTitle(linkNotePG.win, MakeWindowTitle(title));

	FillLayerList((wList_p)linkNotePLs[I_LAYER].control);
	ParamLoadControls(&linkNotePG);
	descTitle = title;

	// and show the dialog
	wShow(linkNoteW);
}

/**
 * Activate note if double clicked
 * \param trk the note
 */

void ActivateLinkNote(track_p trk)
{
	struct extraDataNote_t *xx = GET_EXTRA_DATA( trk, T_NOTE, extraDataNote_t );
	NoteLinkOpen(xx->noteData.linkData.url);
}


/**
 * Describe and enable editing of an existing link note
 *
 * \param trk the existing, valid note
 * \param str the field to put a text version of the note so it will appear on the status line
 * \param len the lenght of the field
 */

void DescribeLinkNote(track_p trk, char * str, CSIZE_T len)
{
	struct extraDataNote_t *xx = GET_EXTRA_DATA( trk, T_NOTE, extraDataNote_t );
	DynString statusLine;

	DynStringMalloc(&statusLine, 80);
	DynStringPrintf(&statusLine,
	                "Weblink (%d) Layer=%d %-.80s (%s)",
	                GetTrkIndex(trk),
	                GetTrkLayer(trk)+1,
	                xx->noteData.linkData.title,
	                xx->noteData.linkData.url);
	strncpy(str, DynStringToCStr(&statusLine), len-1);
	str[len-1] = '\0';
	DynStringFree(&statusLine);
	if ( ! inDescribeCmd ) {
		return;
	}

	linkNoteData.pos = xx->pos;
	linkNoteData.layer = GetTrkLayer( trk );
	linkNoteData.trk = trk;
	strscpy( linkNoteData.url, xx->noteData.linkData.url, sizeof linkNoteData.url );
	strscpy( linkNoteData.title, xx->noteData.linkData.title,
	         sizeof linkNoteData.title );

	CreateEditLinkDialog(_("Update Weblink"));
}

/**
 * Take a new note track element and initialize it. It will be
 * initialized with defaults and can then be edited by the user.
 *
 * \param the newly created trk
 */

void NewLinkNoteUI( coOrd pos )
{
	linkNoteData.pos = pos;
	linkNoteData.layer = curLayer;
	linkNoteData.trk = NULL;
	strscpy( linkNoteData.url, DEFAULTLINKURL, sizeof( linkNoteData.url ) );
	strscpy( linkNoteData.title, DEFAULTLINKTITLE, sizeof( linkNoteData.title ) );

	CreateEditLinkDialog(_("Create Weblink"));
}
