/*
vim: noexpandtab:ts=4:sts=4:sw=4

nudoku

Copyright (C) 2014 - 2024 Michael "jubalh" Vetter - jubalh _a-t_ iodoru.org

LICENCE:
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 3 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, see <http://www.gnu.org/licenses/>.
*/

/* INCLUDES */
#include <cairo.h>				/* cairo_*() */
#include <cairo-pdf.h>			/* cairo_pdf_surface_create */
#include <stdio.h>				/* snprintf() */
#include <stdlib.h>				/* free() */
#include "sudoku.h"				/* sudoku functions */

/* FUNCTIONS */

void draw_grid(const char* stream, cairo_t *cr)
{
	int rectangle_size = 50;

	// small rectangles
	cairo_set_line_width(cr, 1);
	for (int x=0; x < 9; x++)
	{
		for (int y=0; y < 9; y++)
		{
			cairo_rectangle(cr, x*rectangle_size, y*rectangle_size, rectangle_size, rectangle_size);
		}
	}
	cairo_stroke(cr);

	// large rectangles
	cairo_set_line_width(cr, 4);
	for (int x=0; x < 3; x++)
	{
		for (int y=0; y < 3; y++)
		{
			cairo_rectangle(cr, x * rectangle_size * 3, y * rectangle_size * 3, rectangle_size * 3, rectangle_size * 3);
		}
	}
	cairo_stroke(cr);

	// numbers
	cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
	cairo_set_font_size(cr, 25.0);
	int c;
	char tmp_str[2];
	for(int row=0; row < 9; row++)
	{
		for(int	col=0; col < 9; col++)
		{
			c = stream[row*9+col];
			if (c != '.')
			{
				cairo_move_to(cr, rectangle_size/3 + rectangle_size * row, rectangle_size/1.5 + rectangle_size * col);
				snprintf(tmp_str, 2, "%c", c);
				cairo_show_text(cr, tmp_str);
			}
		}
	}
}

void generate_pdf(int difficulty, int sudokus_count, const char* filename)
{
	cairo_surface_t *surface;
	cairo_t *cr;

	surface = cairo_pdf_surface_create(filename, 595, 842);
	cr = cairo_create(surface);

	cairo_set_source_rgb(cr, 0, 0, 0);
	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);

	cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
	cairo_set_font_size(cr, 10.0);

	// difficulty is dependant on translation. let's be safe here and use snprintf() in case it's very long.
	char tmp_str[512];
	snprintf(tmp_str, 512, "sudoku level: %s", difficulty_to_str(difficulty));

	cairo_move_to(cr, 50.0, 70.0);
	cairo_show_text(cr, tmp_str);
	cairo_move_to(cr, 50.0, 80.0);
	cairo_show_text(cr, "generated by nudoku - http://jubalh.github.io/nudoku/");

	cairo_save(cr);

	cairo_scale(cr, 0.5, 0.5);

	int start_x = 0;
	int start_y = 0;
	for (int i=0; i < sudokus_count; i++)
	{
		if (i == 0) {
			// absolute page offset
			cairo_translate(cr, 100, 270);
		}

		if (i % 2 == 0)
		{
			// sudoku in the left column
			cairo_translate(cr, -start_x, 0);
			start_x = 0;
		} else {
			// sudoku in the right column
			cairo_translate(cr, 0, -start_y);
			start_x = 550;
		}

		if ((i%4) / 2 == 0)
		{
			// sudoku at the top of the page
			start_y = 0;
		} else {
			// sudoku at the bottom of the page
			start_y = 600;
		}

		char* stream;
		stream = generate_puzzle(difficulty);

#ifdef DEBUG
		printf("%d: %s\n", i, stream);
#endif // DEBUG

		cairo_translate(cr, start_x, start_y);
		draw_grid(stream, cr);

		if ((i+1) % 4 == 0 && i+1 < sudokus_count)
		{
			// new page
			cairo_translate(cr, 0, -start_y);
			cairo_show_page(cr);
		}

		free(stream);
	}

	cairo_restore(cr);

	cairo_show_page(cr);
	cairo_destroy(cr);
	cairo_surface_destroy(surface);
}

void generate_png(int difficulty, char* filename)
{
	cairo_surface_t *surface;
	cairo_t *cr;

	surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 453, 453);
	cr = cairo_create(surface);

	cairo_set_source_rgb(cr, 0, 0, 0);
	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);

	cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
	cairo_set_font_size(cr, 10.0);

	char* stream;
	stream = generate_puzzle(difficulty);

	cairo_translate(cr, 2, 2);
	draw_grid(stream, cr);
	cairo_surface_write_to_png(surface, filename);

	cairo_destroy(cr);
	cairo_surface_destroy(surface);

	free(stream);
}

void generate_output(int difficulty, char* filename, int sudokuCount, bool isPDF)
{
	if (isPDF)
	{
		generate_pdf(difficulty, sudokuCount, filename);
	} else {
		generate_png(difficulty, filename);
	}
}
