//
// GWDownload.cc
//
// (c) Copyright 1993, San Diego State University -- College of Sciences
//       (See the COPYRIGHT file for more Copyright information)
//
// Implementation of the GWDownload class
//
#include "GWDownload.h"
#include "xvgopher.h"
#include "cursor.h"
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

#define	KEY_TEXT_ITEM		20000
#define	KEY_SAVE			20001
#define	KEY_CANCEL			20002
#define	KEY_OTHER			20003


//***************************************************************************
// GWDownload::GWDownload(Frame par, int download_type)
//
GWDownload::GWDownload(Frame par, int download_type)
{
	parent = par;
	type = download_type;
	button = NULL;
	button_command = NULL;
}


//***************************************************************************
// GWDownload::GWDownload(Frame par, int download_type, char  *btn, char *btncmd)
//
GWDownload::GWDownload(Frame par, int download_type, char  *btn, char *btncmd)
{
	parent = par;
	type = download_type;
	button = btn;
	button_command = btncmd;
}


//***************************************************************************
// void GWDownload::bin_save_notify(Panel_item item, Event *)
// PURPOSE:
//   We get here when the user wants to copy our temporary copy into a more
//   permanent file.
//
void GWDownload::bin_save_notify(Panel_item item, Event *)
{
	GWDownload	*gwindow = (GWDownload *) xv_get(item, XV_KEY_DATA, KEY_GWINDOW);
	Gopher		*gopher = gwindow->gopher;
	Panel_item	txt = (Panel_item) xv_get(item, XV_KEY_DATA, KEY_TEXT_ITEM);
	int	fd = ::open((char *) xv_get(txt, PANEL_VALUE), O_CREAT | O_WRONLY, 0644);
	if (fd < 0)
	{
		gwindow->status("Unable to create file");
		return;
	}

	//
	// Ok, we now have a new file we can write to.  We will just open the
	// temporary file and copy its contents block by block to the new file.
	//
	gwindow->status("Saving...");
	int old = ::open(gopher->filename, O_RDONLY);
	char	buffer[10240];
	int		n;
	while ((n = ::read(old, buffer, 10240)) > 0)
	{
		::write(fd, buffer, n);
	}
	::close(fd);
	::close(old);
	gwindow->status("File saved");
}


//***************************************************************************
// void GWDownload::bin_cancel_notify(Panel_item, Event *)
//
void GWDownload::bin_cancel_notify(Panel_item item , Event *)
{
	GWDownload	*gwindow = (GWDownload *) xv_get(item, XV_KEY_DATA, KEY_GWINDOW);
	delete gwindow;
	Frame	frame = (Frame) xv_get(item, XV_KEY_DATA, KEY_FRAME);
	xv_destroy_safe(frame);
}


//***************************************************************************
// void GWDownload::bin_other_notify(Panel_item, Event *)
//
void GWDownload::bin_other_notify(Panel_item item , Event *)
{
	GWDownload	*gwindow = (GWDownload *) xv_get(item, XV_KEY_DATA, KEY_GWINDOW);
	Gopher		*gopher = gwindow->gopher;
	Panel_item	txt = (Panel_item) xv_get(item, XV_KEY_DATA, KEY_TEXT_ITEM);

	char		command[1000];
	sprintf(command, "%s %s &", gwindow->button_command, gopher->filename);
	system(command);

	sprintf(command, "Started %s on %s", gwindow->button, gopher->filename);
	gwindow->status(command);
}


//***************************************************************************
// Panel_setting GWDownload::bin_text_notify(Panel_item item, Event *event)
//
Panel_setting GWDownload::bin_text_notify(Panel_item item, Event *event)
{
	bin_save_notify(item, event);
	return PANEL_NONE;
}


//***************************************************************************
// int GWDownload::open(Response *resp)
// PURPOSE:
// This will create a prompt window
//
int GWDownload::open(Response *resp)
{
	info = resp;
	compute_location(407, 107);
	frame = (Frame) xv_create(parent, FRAME_CMD,
		XV_X,							next_x,
		XV_Y,							next_y,
		XV_WIDTH,						407,
		XV_HEIGHT,						107,
		FRAME_LABEL,					"Saving a file",
		FRAME_CMD_PIN_STATE,			FRAME_CMD_PIN_IN,
		FRAME_SHOW_RESIZE_CORNER,		FALSE,
		XV_SHOW,						TRUE,
		FRAME_SHOW_FOOTER,				TRUE,
		FRAME_RIGHT_FOOTER,				info->get_server(),
		FRAME_DONE_PROC,				done_proc,
		FRAME_ACCELERATOR,				'q', quit_proc, frame,
		XV_KEY_DATA,					KEY_GWINDOW,	this,
		NULL);
	panel = (Panel) xv_get(frame, FRAME_CMD_PANEL);

	//
	// Create the text field and put a usable default name in it.
	//
	char	*p = strrchr(info->get_command(), '/');
	if (!p)
		p = info->get_command();
	else
		p++;
	char	*str = strdup(p);
	for (p = str; *p; p++)
		if (*p <= ' ' || *p > 126)
			*p = '_';
	Panel_item txt = (Panel_item) xv_create(panel, PANEL_TEXT,
		XV_X,							16,
		XV_Y,							28,
		PANEL_LABEL_STRING,				"Save file as:",
		PANEL_VALUE_DISPLAY_LENGTH,		35,
		PANEL_VALUE_STORED_LENGTH,		80,
		PANEL_VALUE,					str,
		PANEL_NOTIFY_PROC,				bin_text_notify,
		XV_KEY_DATA,					KEY_FRAME,		frame,
		XV_KEY_DATA,					KEY_GWINDOW,	this,
		XV_KEY_DATA,					KEY_GOPHER,		gopher,
		PANEL_INACTIVE,					TRUE,
		NULL);
	delete str;
	xv_set(txt,
		XV_KEY_DATA,					KEY_TEXT_ITEM,	txt,
		NULL);

	//
	// Create the buttons.  There may be two or three buttons.  We need to spread them
	// evenly to make it look better.
	//
	int		ob_x, sb_x, cb_x;
	if (button)
	{
		//
		// There will be three buttons
		//
		ob_x = 107;
		sb_x = 175;
		cb_x = 241;
	}
	else
	{
		//
		// Only two buttons
		//
		sb_x = 141;
		cb_x = 207;
	}
	Panel_item sb = (Panel_item) xv_create(panel, PANEL_BUTTON,
		XV_X,							sb_x,
		XV_Y,							64,
		PANEL_LABEL_STRING,				"Save",
		PANEL_NOTIFY_PROC,				bin_save_notify,
		XV_KEY_DATA,					KEY_FRAME,		frame,
		XV_KEY_DATA,					KEY_GWINDOW,	this,
		XV_KEY_DATA,					KEY_GOPHER,		gopher,
		XV_KEY_DATA,					KEY_TEXT_ITEM,	txt,
		PANEL_INACTIVE,					TRUE,
		NULL);
	Panel_item cb = (Panel_item) xv_create(panel, PANEL_BUTTON,
		XV_X,							cb_x,
		XV_Y,							64,
		PANEL_LABEL_STRING,				"Cancel",
		PANEL_NOTIFY_PROC,				bin_cancel_notify,
		XV_KEY_DATA,					KEY_FRAME,		frame,
		XV_KEY_DATA,					KEY_GWINDOW,	this,
		XV_KEY_DATA,					KEY_TEXT_ITEM,	txt,
		PANEL_INACTIVE,					TRUE,
		NULL);
	Panel_item	ob = NULL;
	if (button)
	{
		ob = (Panel_item) xv_create(panel, PANEL_BUTTON,
			XV_X,							ob_x,
			XV_Y,							64,
			PANEL_LABEL_STRING,				button,
			PANEL_NOTIFY_PROC,				bin_other_notify,
			XV_KEY_DATA,					KEY_FRAME,		frame,
			XV_KEY_DATA,					KEY_GWINDOW,	this,
			XV_KEY_DATA,					KEY_TEXT_ITEM,	txt,
			PANEL_INACTIVE,					TRUE,
			NULL);
	}

	//
	// Associate the panel items with the frame so we can get at them later on
	//
	xv_set(frame,
		XV_KEY_DATA,					KEY_SAVE,		sb,
		XV_KEY_DATA,					KEY_CANCEL,		cb,
		XV_KEY_DATA,					KEY_OTHER,		ob,
		XV_KEY_DATA,					KEY_TEXT_ITEM,	txt,
		NULL);
	//
	// Now we need to build the connection and get information from it
	//
	frame_busy(frame);
	status("Building connection...");
	gopher = new Gopher(this);
	if (gopher->open(info->get_server(), info->get_port()) == NOTOK)		// Connection
		return NOTOK;
	gopher->read(info->get_type(), info->get_command());					// Get info

	return OK;
}


//***************************************************************************
// void GWDownload::display()
// PURPOSE:
//   This is called when the receive of a file has been completed.
//
void GWDownload::display()
{
	//
	// Now make the items in the window active so that the file can be saved
	//
	frame_unbusy(frame);
	Panel_item	b = (Panel_item) xv_get(frame, XV_KEY_DATA, KEY_SAVE);
	xv_set(b, PANEL_INACTIVE, FALSE, NULL);
	b = (Panel_item) xv_get(frame, XV_KEY_DATA, KEY_CANCEL);
	xv_set(b, PANEL_INACTIVE, FALSE, NULL);
	b = (Panel_item) xv_get(frame, XV_KEY_DATA, KEY_TEXT_ITEM);
	xv_set(b, PANEL_INACTIVE, FALSE, NULL);
	b = (Panel_item) xv_get(frame, XV_KEY_DATA, KEY_OTHER);
	if (b)
		xv_set(b, PANEL_INACTIVE, FALSE, NULL);
}


