/*
  Hatari - printer.c

  This file is distributed under the GNU General Public License, version 2
  or at your option any later version. Read the file gpl.txt for details.

  Printer communication. When bytes are sent from the ST they are sent to these
  functions via 'Printer_TransferByteTo()'. This will then open a file and
  direct the output to this. These bytes are buffered up (to improve speed) and
  this also allow us to detect when the stream goes into idle - at which point
  we close the file/printer.
*/
const char Printer_fileid[] = "Hatari printer.c";

#include "main.h"
#include "configuration.h"
#include "file.h"
#include "paths.h"
#include "printer.h"
#include "log.h"

#define PRINTER_DEBUG 0
#if PRINTER_DEBUG
#define Dprintf(a) printf a
#else
#define Dprintf(a)
#endif

/* After ~4 seconds (4*50 VBLs), flush & close printer */
#define PRINTER_IDLE_CLOSE   (4*50)

static int nIdleCount;
static int bUnflushed;

static FILE *pPrinterHandle;


/*-----------------------------------------------------------------------*/
/**
 * Initialise Printer
 */
void Printer_Init(void)
{
	char *separator;
	Dprintf((stderr, "Printer_Init()\n"));

	/* disabled from config/command line? */
	if (!ConfigureParams.Printer.bEnablePrinting ||
	    !ConfigureParams.Printer.szPrintToFileName[0])
		return;

	/* printer name without path? */
	separator = strrchr(ConfigureParams.Printer.szPrintToFileName, PATHSEP);
	if (!separator)
		return;
	
	*separator = '\0';
	if (!File_DirExists(ConfigureParams.Printer.szPrintToFileName)) {
		Log_AlertDlg(LOG_ERROR, "Printer output file directory inaccessible. Printing disabled.");
		ConfigureParams.Printer.bEnablePrinting = false;
	}
	*separator = PATHSEP;

	Dprintf((stderr, "Filename for printing: %s \n", ConfigureParams.Printer.szPrintToFileName));
}


/*-----------------------------------------------------------------------*/
/**
 * Uninitialise Printer
 */
void Printer_UnInit(void)
{
	Dprintf((stderr, "Printer_UnInit()\n"));

	/* Close any open files */
	pPrinterHandle = File_Close(pPrinterHandle);
	bUnflushed = false;
	nIdleCount = 0;
}


/*-----------------------------------------------------------------------*/
/**
 * Pass byte from emulator to printer.  Opens the printer file appending
 * if it isn't already open. Returns false if connection to "printer"
 * failed
 */
bool Printer_TransferByteTo(uint8_t Byte)
{
	/* Do we want to output to a printer/file? */
	if (!ConfigureParams.Printer.bEnablePrinting)
		return false;   /* Failed if printing disabled */

	/* Have we made a connection to our printer/file? */
	if (!pPrinterHandle)
	{
		/* open printer file... */
		pPrinterHandle = File_Open(ConfigureParams.Printer.szPrintToFileName, "a+b");
		if (!pPrinterHandle)
		{
			Log_AlertDlg(LOG_ERROR, "Printer output file open failed. Printing disabled.");
			ConfigureParams.Printer.bEnablePrinting = false;
			return false;
		}
	}
	if (fputc(Byte, pPrinterHandle) != Byte)
	{
		Log_Printf(LOG_ERROR, "Printer_TransferByteTo() writing failed!\n");
		return false;
	}
	bUnflushed = true;
	return true;
}


/*-----------------------------------------------------------------------*/
/**
 * Empty printer buffer, and if remains idle for set time close connection
 * (ie close file, stop printer)
 */
void Printer_CheckIdleStatus(void)
{
	/* Is anything waiting for printer? */
	if (bUnflushed)
	{
		fflush(pPrinterHandle);
		bUnflushed = false;
		nIdleCount = 0;
	}
	else
	{
		nIdleCount++;
		/* Has printer been idle? */
		if (nIdleCount >= PRINTER_IDLE_CLOSE)
		{
			/* Close printer output */
			Printer_UnInit();
		}
	}
}
