/*
 * Copyright 2010 Ole Loots <ole@monochrom.net>
 *
 * This file is part of NetSurf, http://www.netsurf-browser.org/
 *
 * NetSurf 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; version 2 of the License.
 *
 * NetSurf 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, see <http://www.gnu.org/licenses/>.
 */

#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mint/osbind.h>
#include <cflib.h>

#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
#include "desktop/browser.h"
#include "desktop/mouse.h"
#include "desktop/textinput.h"
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"

#include "atari/gui.h"
#include "atari/rootwin.h"
#include "atari/misc.h"
#include "atari/clipboard.h"
#include "utils/nsoption.h"
#include "atari/res/netsurf.rsh"
#include "atari/ctxmenu.h"


#define CNT_INVALID 0
#define CNT_BROWSER 64
#define CNT_HREF 128
#define CNT_SELECTION 256
#define CNT_INTERACTIVE 512
#define CNT_IMG 1024

bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);

struct s_context_info {
	unsigned long flags;
	struct browser_window_features ccdata;
};

struct s_context_info ctxinfo;

static struct s_context_info * get_context_info( struct gui_window * gw, short mx, short my )
{
	hlcache_handle *h;
	GRECT area;
	struct browser_window * bw = gw->browser->bw;
	int sx, sy;

	h = browser_window_get_content(bw);
	ctxinfo.flags = 0;

	window_get_grect(gw->root, BROWSER_AREA_CONTENT, &area);
	if (POINT_WITHIN(mx, my, area)) {

		mx -= area.g_x;
		my -= area.g_y;

		if (browser_window_has_content(bw) == false ||
				content_get_type(h) != CONTENT_HTML){
			return(&ctxinfo);
		}

		ctxinfo.flags |= CNT_BROWSER;

		gui_window_get_scroll(gw, &sx, &sy);

		browser_window_get_features( gw->browser->bw, mx+sx, my+sy,
				&ctxinfo.ccdata);

		if( ctxinfo.ccdata.link ){
			ctxinfo.flags |= CNT_HREF;
		}
		if( ctxinfo.ccdata.object) {
			if( content_get_type(ctxinfo.ccdata.object) == CONTENT_IMAGE ){
				ctxinfo.flags |= CNT_IMG;
			}
		}
		if ( ctxinfo.ccdata.form_features == CTX_FORM_TEXT )
			ctxinfo.flags |= (CNT_INTERACTIVE | CNT_SELECTION);
	}

	return(&ctxinfo);


}

/***
 * Generates an unique filename for temp. files
 * The generated filename includes the path.
 * If TMPDIR environmenrt vairable is set, this will be used as path,
 * otherwise U:\tmp\
 * \param prefix
 * \param sufffix
 * \return pointer to static buffer owned by get_tmpfilename()
 */
static char * get_tmpfilename(const char * prefix, const char * suffix)
{
    int i=0;
    static char tmpfilename[PATH_MAX];
    char * tmpdir;
    const char * tmp_path_suffix = "";

    // TODO: make function public?
    tmpdir = getenv("TMPDIR");
    if(tmpdir == NULL){
        tmpdir = (char*)"u:\\tmp\\";
    }

    if(tmpdir[strlen(tmpdir)-1] != '\\'){
        tmp_path_suffix = "\\";
    }

    do{
        /* generate a new filename: */
        snprintf(tmpfilename, PATH_MAX, "%s%s%s%d%s", tmpdir,
                 tmp_path_suffix, prefix, i++, suffix);
        /* check with cflib: */
    } while(file_exists(tmpfilename));

    return(tmpfilename);
}

//TODO: do not open popup for gui_window, but for a rootwin?
void context_popup(struct gui_window * gw, short x, short y)
{

#define POP_FIRST_ITEM POP_CTX_CUT_SEL
#define POP_LAST_ITEM POP_CTX_SAVE_LINK_AS

	OBJECT * pop;
	int choice;
	struct s_context_info * ctx;
	unsigned long size;
	const char * data;
	FILE * fp_tmpfile;
	char cmdline[128];
	/* skip first byte, which must hold length of commandline: */
	char * tempfile = &cmdline[1];
	char * editor;
	MENU pop_menu, me_data;

	pop = gemtk_obj_get_tree( POP_CTX );
	if (pop == NULL)
        	return;
	ctx = get_context_info(gw, x, y);

    /*
        Disable all items by default:
    */
	for( choice = POP_FIRST_ITEM; choice<=POP_LAST_ITEM; choice++ ){
		SET_BIT(pop[ choice ].ob_state, OS_DISABLED, 1);
	}

	if( ctx->flags & CNT_INTERACTIVE ){
        	SET_BIT(pop[ POP_CTX_PASTE_SEL ].ob_state, OS_DISABLED, 0);
    	}

	if( (ctx->flags & CNT_BROWSER) ){
		SET_BIT(pop[ POP_CTX_SELECT_ALL ].ob_state, OS_DISABLED, 0);
		SET_BIT(pop[ POP_CTX_COPY_SEL ].ob_state, OS_DISABLED, 0);
		SET_BIT(pop[ POP_CTX_VIEW_SOURCE ].ob_state, OS_DISABLED, 0);
	}

	if( ctx->flags & CNT_HREF ){
		SET_BIT(pop[ POP_CTX_COPY_LINK ].ob_state, OS_DISABLED, 0);
        SET_BIT(pop[ POP_CTX_OPEN_NEW ].ob_state, OS_DISABLED, 0);
        SET_BIT(pop[ POP_CTX_SAVE_LINK_AS ].ob_state, OS_DISABLED, 0);
	}

	if( ctx->flags & CNT_IMG ){
		SET_BIT(pop[ POP_CTX_SAVE_AS ].ob_state, OS_DISABLED, 0);
		SET_BIT(pop[ POP_CTX_COPY_URL ].ob_state, OS_DISABLED, 0);
		SET_BIT(pop[ POP_CTX_OPEN_NEW ].ob_state, OS_DISABLED, 0);
	}

	// point mn_tree tree to states popup:
    pop_menu.mn_tree = gemtk_obj_get_tree(POP_CTX);
    pop_menu.mn_menu = 0;
    pop_menu.mn_item = POP_CTX_CUT_SEL;
    pop_menu.mn_scroll = SCROLL_NO;
    pop_menu.mn_keystate = 0;

	menu_popup(&pop_menu, x, y, &me_data);
    choice = me_data.mn_item;

	switch( choice ){
		case POP_CTX_COPY_SEL:
			browser_window_key_press(gw->browser->bw, KEY_COPY_SELECTION);
		break;

		case POP_CTX_CUT_SEL:
			browser_window_key_press(gw->browser->bw, KEY_CUT_SELECTION);
		break;

		case POP_CTX_PASTE_SEL:
			browser_window_key_press(gw->browser->bw, KEY_PASTE);
		break;

		case POP_CTX_SELECT_ALL:
			browser_window_key_press(gw->browser->bw, KEY_SELECT_ALL);
		break;

		case POP_CTX_SAVE_AS:
			if (ctx->ccdata.object != NULL) {
				if( hlcache_handle_get_url(ctx->ccdata.object) != NULL ) {
					browser_window_navigate(
						gw->browser->bw,
						hlcache_handle_get_url(ctx->ccdata.object),
						browser_window_get_url(gw->browser->bw),
						BW_NAVIGATE_DOWNLOAD,
						NULL,
						NULL,
						NULL
						);
				}
			}

		case POP_CTX_SAVE_LINK_AS:
			if (ctx->ccdata.link != NULL) {
				nserror error;

				error = browser_window_navigate(
					gw->browser->bw,
					ctx->ccdata.link,
					browser_window_get_url(gw->browser->bw),
					BW_NAVIGATE_DOWNLOAD,
					NULL,
					NULL,
					NULL);

				if (error != NSERROR_OK) {
					warn_user(messages_get_errorcode(error), 0);
				}
			}

		break;

		case POP_CTX_COPY_URL:
			if ((ctx->flags & CNT_IMG) && (ctx->ccdata.object != NULL)) {
				if( hlcache_handle_get_url(ctx->ccdata.object) != NULL ){
					scrap_txt_write((char*)nsurl_access(
							hlcache_handle_get_url(ctx->ccdata.object)));
				}
			}
		break;

		case POP_CTX_COPY_LINK:
			if ((ctx->flags & CNT_HREF) &&
			    (ctx->ccdata.link != NULL)) {
				scrap_txt_write((char*)nsurl_access(ctx->ccdata.link));
			}
		break;

		case POP_CTX_OPEN_NEW:
			if ((ctx->flags & CNT_HREF) &&
			    (ctx->ccdata.link != NULL)) {
				nserror error;

				error = browser_window_create(
					BW_CREATE_HISTORY | BW_CREATE_CLONE,
					ctx->ccdata.link,
					browser_window_get_url(gw->browser->bw),
					gw->browser->bw,
					NULL);
				if (error != NSERROR_OK) {
					warn_user(messages_get_errorcode(error), 0);
				}
			}
		break;

		case POP_CTX_VIEW_SOURCE:
			editor = nsoption_charp(atari_editor);
			if (editor != NULL && strlen(editor)>0) {
				data = content_get_source_data(browser_window_get_content(gw->browser->bw),
												&size);
				if (size > 0 && data != NULL){
				    snprintf(tempfile, 127, "%s", get_tmpfilename("ns-", ".html"));
				    /* the GEMDOS cmdline contains the length of the commandline
				       in the first byte: */
				    cmdline[0] = (unsigned char)strlen(tempfile);
					LOG(("Creating temporay source file: %s\n", tempfile));
					fp_tmpfile = fopen(tempfile, "w");
					if (fp_tmpfile != NULL){
						fwrite(data, size, 1, fp_tmpfile);
						fclose(fp_tmpfile);

						// Send SH_WDRAW to notify files changed:
						gemtk_send_msg(SH_WDRAW, 0, -1, 0, 0, 0, 0);

                        // start application:
						if(strlen(tempfile)<=125){
							shel_write(1, 1, 1, editor, cmdline);
						}
					} else {
						printf("Could not open temp file: %s!\n", tempfile );
					}

				} else {
					LOG(("Invalid content!"));
				}
			} else {
				form_alert(0, "[1][Set option \"atari_editor\".][OK]");
			}
		break;

		default: break;
	}

#undef POP_FIRST_ITEM
#undef POP_LAST_ITEM

}
