/*
 * Copyright (C) 2014-2024 m-privacy GmbH
 *
 * This 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 software 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 software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 * USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Multiline_Output.H>

#include <rdr/mutex.h>
#include <rfb/LogWriter.h>

#include "parameters.h"

#include "PrintDialog.h"

static rfb::LogWriter vlog("PrintDialog");

MUTEX_TYPE PrintDialog::print_file_lock;

PrintDialog::PrintDialog(const char* window_title)
	: Fl_Double_Window(window_width, window_height, window_title) {

	MUTEX_INIT_NOCHECK(&print_file_lock);

	vlog.info("New PrintDialog");

#if !defined(__APPLE__)
		resize(Fl::w() / 2 - window_width / 2,
		       Fl::h() / 2 - window_height / 2,
		       window_width, window_height);
		begin();
		ok_butt = new Fl_Button(window_width / 2 + margin,
					window_height - butt_height - margin,
					butt_width, butt_height, "Drucken");
		cancel_butt = new Fl_Button(window_width / 2 - butt_width - margin,
					    window_height - butt_height - margin,
					    butt_width, butt_height, "Verwerfen") ;
		text_output = new Fl_Multiline_Output(margin,
						      margin,
						      window_width - 2 * margin,
						      window_height - butt_height - 3 * margin,
						      NULL);
		text_output->value("Ein Druckauftrag wurde übermittelt.\n"
				   "Möchten sie ihn auf dem als Standard voreingestellten\n"
				   "Drucker ausgeben oder verwerfen?");
		end();
		ok_butt->callback(this->callback_ok, this);
		cancel_butt->callback(this->callback_cancel, this);
#endif
}


PrintDialog::~PrintDialog() {
	delete ok_butt;
	delete cancel_butt;
	delete text_output;
	if (print_file) {
		free(print_file);
	}
	MUTEX_DESTROY(&print_file_lock);
}


void PrintDialog::print(char * cur_file) {
	char * print_cmd;

	print_cmd = (char *) malloc(strlen(cur_file) + strlen(printCommand.getData()) + 1);
	if (!print_cmd) {
		vlog.error("Failed to allocate memory for PrintCommand. Something went really wrong. Aborting printing...");
		return;
	}
	sprintf(print_cmd, "%s \"%s\"", printCommand.getData(), cur_file);
	vlog.debug("Calling system: %s", print_cmd);
	system(print_cmd);
	free(print_cmd);
}


void PrintDialog::callback_ok(Fl_Widget *widget, void *data) {
	vlog.debug("Ok, drucken.");
	PrintDialog* my_pd = (PrintDialog*)data;

	my_pd->hide(); // This actually gets called twice this time (see cleanup()), but according to the docs, it should be harmless
	my_pd->print(my_pd->print_file);
	my_pd->cleanup();
}


void PrintDialog::callback_cancel(Fl_Widget *widget, void *data) {
	vlog.debug("Nicht drucken.");
	PrintDialog* my_pd = (PrintDialog*)data;
	my_pd->cleanup();
}


void PrintDialog::new_job(const char* pdf_file) {
#if defined(WIN32) || defined(WIN64)
	vlog.debug("Thread %lu: New print job: %s. Waiting for lock (if another print job is still running)", GetCurrentThreadId(), pdf_file);
#elif defined(__APPLE__)
	vlog.debug("Thread %u: New print job: %s. Waiting for lock (if another print job is still running)", gettid(), pdf_file);
#else
	vlog.debug("Thread %lu: New print job: %s. Waiting for lock (if another print job is still running)", gettid(), pdf_file);
#endif
	MUTEX_LOCK(&print_file_lock);
	vlog.debug("Done waiting for lock. Printing %s", pdf_file);

	print_file = strdup(pdf_file);
	text_output->value("Ein weiterer Druckauftrag wurde übermittelt.\n"
			   "Möchten sie ihn auf dem als Standard voreingestellten\n"
			   "Drucker ausgeben oder verwerfen?");
	if (quickPrint) {
		print(print_file);
		cleanup();
	} else {
#if defined(WIN32) || defined(WIN64)
		POINT cursorPos;

		if(GetCursorPos(&cursorPos))
			position(cursorPos.x, cursorPos.y);
#endif
		show();
	}
}

void PrintDialog::cleanup() {
	hide();

	if (print_file) {
		if (unlink(print_file)) {
			vlog.error("Error: could not delete %s", print_file);
		} else {
			vlog.debug("Deleted: %s", print_file);
		}

		free(print_file);
		print_file = NULL;
		MUTEX_UNLOCK(&print_file_lock);
	}
}
