
#include <stdio.h>
#include <string.h>
#include "app.h"
#include "GenCard.h"

/*
 *  Composite together the pieces of a 7th Edition Magic card.
 */


/*
 *  Draw a normal card (as opposed to a flip card).
 *
 *  This function does all kinds of things like compositing the
 *  art onto the correct background colour, blending hybrid cards,
 *  drawing text for the card name, type, etc as well as scaling
 *  down font sizes to ensure rules text fits into the text box,
 *  and also draws the mana cost, expansion symbol, artist name,
 *  and even draws bevels around art and text boxes.
 *
 *  In short: it does everything, except not flip cards or split cards.
 *  There are other functions below which handle those kinds of cards.
 */
Image * create_card_image_7th_ed_normal(Card *card, Colour border_colour)
{
	Graphics *g;
	Image *full;
	Image *art;
	Image *scaled_art;
	char *filename;

	if (logfile)
		fprintf(logfile, "Viewing card %s\n", card->name);

	full = form_card_template_3_7th_ed(border_colour,
			card->bg1, card->tb1, card->tb_col1,
			card->bg2, card->tb2, card->tb_col2,
			card->bg3, card->tb3, card->tb_col3,
			0);

	if (full == NULL) {
		if (logfile != NULL) {
			fprintf(logfile,
				"\tCouldn't read template image file %s\n", card->bg);
		}
		return NULL;
	}

	/* Draw into the image now. */
	g = app_get_image_graphics(full);

	if (card->artfile[0])
	{
		char *artfile = find_image_source("./", art_dir,
						card->artfile, "");
		if (artfile != NULL) {
			art = app_read_image(artfile, 32);
			app_free(artfile);
		}
		else
			art = NULL;

		if (art != NULL)
		{
			scaled_art = app_scale_image(art,
					rect(0,0,570,460),
					largest_rect(app_get_image_area(art), 570, 460));
			app_draw_image(g, rect(87,107,570,460),
				scaled_art, rect(0,0,570,460));
			app_del_image(scaled_art);
			app_del_image(art);
		}
		else {
			if (logfile)
				fprintf(logfile, "Couldn't find or load artwork file %s\n", card->artfile);
		}
	}

	if (card->name[0])
	{
		app_set_font(g, name_font);
		draw_white_shadow_text_style(g, name_fonts,
				rect(58, 35, full->width-60, 64),
				(ALIGN_LEFT | VALIGN_TOP | LR_TB),
				card->name, (int) strlen(card->name), card->namefnt);
	}

	if (card->cost[0])
	{
		if (mana_font != NULL)
		{
			app_set_font(g, mana_font);
			app_draw_text(g, rect(58, 35, full->width-115, 64),
					(ALIGN_RIGHT | VALIGN_TOP | LR_TB),
					card->cost, (int) strlen(card->cost));
		}
		else
		{
			Rect r;
			int name_width;
			int costlen = (int) strlen(card->cost);
			char *coststyle = app_alloc(costlen + 1);
			memset(coststyle, MANA_FONT, costlen);

			/* this is the full width of the name bar */
			r = rect(58, 35, full->width-115, 64);

			/* try to scale down the casting cost to fit
			 * if the name is very long
			 */
			if (card->name[0])
			{
				name_width = app_text_width(name_font,
						full->width-60,
						card->name,
						(int) strlen(card->name));
				if (name_width < full->width - 250)
				{
					/* possibly long, but not too long;
					 * if it's longer than this just draw
					 * the casting cost over the name.
					 */
					r.x += name_width;
					r.width -= name_width;
				}
			}

			fit_text(g, fonts_7th_ed,
					r, (ALIGN_RIGHT | VALIGN_CENTER | LR_TB),
					56, 16,
					card->cost, costlen, coststyle,
					NULL, 0, NULL,
					1);
			app_free(coststyle);
		}
	}

	if (card->expsym[0])
		filename = card->expsym;
	else
		filename = default_expansion;
	filename = find_image_source("./", symbols, filename,
				rarity_to_trailer(filename, card->rarity));
	if (filename != NULL) {
		art = app_read_image(filename, 32);
		app_free(filename);
	}
	else
		art = NULL;

	if (art != NULL)
	{
		Rect sr = app_get_image_area(art);
		Rect dr;
		dr.y = 590;
		dr.height = 40;
		dr.width = sr.width * dr.height / sr.height;
		dr.x = full->width - 60 - dr.width;
		app_draw_image(g, dr, art, sr);
		app_del_image(art);
	}

	if (card->type[0])
	{
		app_set_font(g, type_font);
		draw_white_shadow_text(g,
				rect(74, 575, full->width-60, 60),
				(ALIGN_LEFT | VALIGN_CENTRE | LR_TB),
				card->type, (int) strlen(card->type));
	}

	if ((card->text[0]) || (card->flavor[0]))
	{
		fit_text(g, fonts_7th_ed,
			rect(95, 653, 554, 282),
			(ALIGN_LEFT | LR_TB),
			40, 16,
			card->text, (int) strlen(card->text), card->textfnt,
			card->flavor, (int) strlen(card->flavor), card->flavfnt,
			1);
	}

	if (card->powtgh[0])
	{
		app_set_font(g, type_font);
		draw_white_shadow_text(g,
				rect(full->width - 500, 950, 450, 50),
				(ALIGN_RIGHT | VALIGN_CENTRE | LR_TB),
				card->powtgh, (int) strlen(card->powtgh));
	}

	if (card->artist[0])
	{
		char *artcopyright = app_alloc(10 + strlen(card->artist));
		artcopyright[0] = '\0';
		//strcpy(artcopyright, "Illus. ");
		strcat(artcopyright, card->artist);

		app_set_font(g, artist_font);
		draw_white_shadow_text(g, rect(58, 950, 550, 50),
				(ALIGN_LEFT | VALIGN_CENTRE | LR_TB),
				artcopyright, (int) strlen(artcopyright));
	}

	if (card->number[0])
	{
		app_set_font(g, number_font);
		draw_white_shadow_text_1(g, rect(30, 990, full->width-60, 20),
				(ALIGN_CENTRE | VALIGN_CENTRE | LR_TB),
				card->number, (int) strlen(card->number));
	}

	app_del_graphics(g);

	return full;
}

/*
 *  An alternative to the function above, which draws a flip-card.
 */
Image * create_card_image_7th_ed_flipped(Card *card, Colour border_colour)
{
	Graphics *g;
	Image *full;
	Image *art;
	Image *scaled_art;
	Image *rot;
	char *filename;
	int gap = 46;
	int art_done = 0;
	Card *flip = card->flip;

	if (logfile && flip)
		fprintf(logfile, "Viewing flip-card %s /// %s\n", card->name, flip->name);

	full = form_card_template_3_7th_ed(border_colour,
			card->bg1, card->tb1, card->tb_col1,
			card->bg2, card->tb2, card->tb_col2,
			card->bg3, card->tb3, card->tb_col3,
			1);

	if (flip->bg[0]) {
		rot = form_card_template_3_7th_ed(border_colour,
			flip->bg1, flip->tb1, flip->tb_col1,
			flip->bg2, flip->tb2, flip->tb_col2,
			flip->bg3, flip->tb3, flip->tb_col3,
			1);

		rotate_image_32bpp_180_degrees(rot);
	}
	else {
		rot = NULL;
	}

	if (full == NULL) {
		if (logfile != NULL) {
			fprintf(logfile,
				"\tCouldn't make template image file %s\n", card->bg);
		}
		return NULL;
	}

	/* Draw into the image now. */
	g = app_get_image_graphics(full);

	if (card->name[0])
	{
		app_set_font(g, name_font);
		draw_white_shadow_text_style(g, name_fonts,
				rect(58, 35, full->width-60, 64),
				(ALIGN_LEFT | VALIGN_TOP | LR_TB),
				card->name, (int) strlen(card->name), card->namefnt);
	}

	if (card->cost[0])
	{
		if (mana_font != NULL)
		{
			app_set_font(g, mana_font);
			app_draw_text(g, rect(58, 35, full->width-115, 64),
					(ALIGN_RIGHT | VALIGN_TOP | LR_TB),
					card->cost, (int) strlen(card->cost));
		}
		else
		{
			Rect r;
			int name_width;
			int costlen = (int) strlen(card->cost);
			char *coststyle = app_zero_alloc(costlen+1);
			memset(coststyle, MANA_FONT, costlen);

			/* this is the full width of the name bar */
			r = rect(58, 35, full->width-115, 64);

			/* try to scale down the casting cost to fit
			 * if the name is very long
			 */
			if (card->name[0])
			{
				name_width = app_text_width(name_font,
						full->width-60,
						card->name,
						(int) strlen(card->name));
				if (name_width < full->width - 250)
				{
					/* possibly long, but not too long;
					 * if it's longer than this just draw
					 * the casting cost over the name.
					 */
					r.x += name_width;
					r.width -= name_width;
				}
			}

			fit_text(g, fonts_7th_ed,
					r, (ALIGN_RIGHT | VALIGN_CENTER | LR_TB),
					56, 16,
					card->cost, costlen, coststyle,
					NULL, 0, NULL,
					1);
			app_free(coststyle);
		}
	}

	if (card->type[0])
	{
		app_set_font(g, type_font);
		draw_white_shadow_text(g,
				rect(70, 260, full->width-60, 60),
				(ALIGN_LEFT | VALIGN_CENTRE | LR_TB),
				card->type, (int) strlen(card->type));
	}

	if (card->text[0])
	{
		fit_text(g, fonts_7th_ed,
			rect(95, 107, 554, 144),
			(ALIGN_LEFT | LR_TB),
			40, 16,
			card->text, (int) strlen(card->text), card->textfnt,
			card->flavor, (int) strlen(card->flavor), card->flavfnt,
			1);
	}

	if (card->powtgh[0])
	{
		app_set_font(g, type_font);
		draw_white_shadow_text(g,
				rect(full->width - 500, 260, 440, 60),
				(ALIGN_RIGHT | VALIGN_CENTRE | LR_TB),
				card->powtgh, (int) strlen(card->powtgh));
	}


	if (rot) {
		app_del_graphics(g);
		g = app_get_image_graphics(rot);
	}
	else {
		rotate_image_32bpp_180_degrees(full);
	}

	app_set_font(g, name_font);
	draw_white_shadow_text_style(g, name_fonts,
				rect(58, 35+gap, full->width-60, 64),
				(ALIGN_LEFT | VALIGN_TOP | LR_TB),
				flip->name, (int) strlen(flip->name), flip->namefnt);

	if (flip->cost[0])
	{
		if (mana_font != NULL)
		{
			app_set_font(g, mana_font);
			app_draw_text(g, rect(58, 35+gap, full->width-115, 64),
					(ALIGN_RIGHT | VALIGN_TOP | LR_TB),
					flip->cost, (int) strlen(flip->cost));
		}
		else
		{
			Rect r;
			int name_width;
			int costlen = (int) strlen(flip->cost);
			char *coststyle = app_zero_alloc(costlen+1);
			memset(coststyle, MANA_FONT, costlen);

			/* this is the full width of the name bar */
			r = rect(58, 35+gap, full->width-115, 64);

			/* try to scale down the casting cost to fit
			 * if the name is very long
			 */
			if (flip->name[0])
			{
				name_width = app_text_width(name_font,
						full->width-60,
						flip->name,
						(int) strlen(flip->name));
				if (name_width < full->width - 250)
				{
					/* possibly long, but not too long;
					 * if it's longer than this just draw
					 * the casting cost over the name.
					 */
					r.x += name_width;
					r.width -= name_width;
				}
			}

			fit_text(g, fonts_7th_ed,
					r, (ALIGN_RIGHT | VALIGN_CENTER | LR_TB),
					56, 16,
					flip->cost, costlen, coststyle,
					NULL, 0, NULL,
					1);
			app_free(coststyle);
		}
	}

	if (flip->type[0])
	{
		app_set_font(g, type_font);
		draw_white_shadow_text(g,
				rect(70, 260+gap, full->width-60, 60),
				(ALIGN_LEFT | VALIGN_CENTRE | LR_TB),
				flip->type, (int) strlen(flip->type));
	}

	if (flip->text[0])
	{
		fit_text(g, fonts_7th_ed,
			rect(95, 107+gap, 554, 144),
			(ALIGN_LEFT | LR_TB),
			40, 16,
			flip->text, (int) strlen(flip->text), flip->textfnt,
			flip->flavor, (int) strlen(flip->flavor), flip->flavfnt,
			1);
	}

	if (flip->powtgh[0])
	{
		app_set_font(g, type_font);
		draw_white_shadow_text(g,
				rect(full->width - 500, 260+gap, 440, 60),
				(ALIGN_RIGHT | VALIGN_CENTRE | LR_TB),
				flip->powtgh, (int) strlen(flip->powtgh));
	}

	if (rot) {
		rotate_image_32bpp_180_degrees(rot);
		blend_two_images_32bpp_vertically(full, rot, BLEND_DIST);
		app_del_image(rot);
	}
	else {
		rotate_image_32bpp_180_degrees(full);
	}

	app_del_graphics(g);

	g = app_get_image_graphics(full);

	if ((card->artfile[0] != '\0') && (flip->artfile[0] != '\0'))
	{
		/* Blend the art, the flipped art is rotated first. */
		char *artfile = find_image_source("./", art_dir,
						card->artfile, "");
		if (artfile != NULL) {
			art = app_read_image(artfile, 32);
			app_free(artfile);
		}
		else {
			art = NULL;
			if (logfile)
				fprintf(logfile, "Couldn't find artwork file %s\n", card->artfile);
		}

		artfile = find_image_source("./", art_dir,
						flip->artfile, "");
		if (artfile != NULL) {
			rot = app_read_image(artfile, 32);
			app_free(artfile);
		}
		else {
			rot = NULL;
			if (logfile)
				fprintf(logfile, "Couldn't find artwork file %s\n", flip->artfile);
		}

		if ((art != NULL) && (rot != NULL))
		{
			Graphics *g2;

			/* Scale the upright card art. */
			scaled_art = app_scale_image(art,
					rect(0,0,300,322),
					largest_rect(app_get_image_area(art), 300, 322));
			app_del_image(art);

			/* Make a third-white image from scaled art. */
			art = app_new_image(570, 322, 32);
			g2 = app_get_image_graphics(art);
			app_draw_image(g2, rect(0,0,300,322),
					scaled_art, rect(0,0,300,322));
			app_del_graphics(g2);
			app_del_image(scaled_art);

			/* Scale the rotated flip card art */
			rotate_image_32bpp_180_degrees(rot);

			scaled_art = app_scale_image(rot,
					rect(0,0,300,322),
					largest_rect(app_get_image_area(rot), 300, 322));
			app_del_image(rot);

			/* Make a third-white image from rotated art. */
			rot = app_new_image(570, 322, 32);
			g2 = app_get_image_graphics(rot);
			app_draw_image(g2, rect(270,0,300,322),
					scaled_art, rect(0,0,300,322));
			app_del_graphics(g2);
			app_del_image(scaled_art);

			/* Blend then draw. */
			blend_two_images_32bpp_horizontally(art,
						rot, BLEND_FLIP_ART);

			app_draw_image(g, rect(87,337,570,322),
				art, rect(0,0,570,322));

			art_done = 1;
		}
		if (art)
			app_del_image(art);
		else if (logfile)
			fprintf(logfile, "Couldn't load artwork file %s\n", card->artfile);
		if (rot)
			app_del_image(rot);
		else if (logfile)
			fprintf(logfile, "Couldn't load artwork file %s\n", flip->artfile);
	}
	if ((! art_done) && (card->artfile[0] != '\0'))
	{
		char *artfile = find_image_source("./", art_dir,
						card->artfile, "");
		if (artfile != NULL) {
			art = app_read_image(artfile, 32);
			app_free(artfile);
		}
		else
			art = NULL;

		if (art != NULL)
		{
			scaled_art = app_scale_image(art,
					rect(0,0,570,322),
					largest_rect(app_get_image_area(art), 570, 322));
			app_draw_image(g, rect(87,337,570,322),
				scaled_art, rect(0,0,570,322));
			app_del_image(scaled_art);
			app_del_image(art);
			art_done = 1;
		}
		else {
			if (logfile)
				fprintf(logfile, "Couldn't find or load artwork file %s\n", card->artfile);
		}
	}
	if ((! art_done) && (flip->artfile[0] != '\0'))
	{
		char *artfile = find_image_source("./", art_dir,
						flip->artfile, "");
		if (artfile != NULL) {
			art = app_read_image(artfile, 32);
			app_free(artfile);
		}
		else
			art = NULL;

		if (art != NULL)
		{
			scaled_art = app_scale_image(art,
					rect(0,0,570,322),
					largest_rect(app_get_image_area(art), 570, 322));
			app_draw_image(g, rect(87,337,570,322),
				scaled_art, rect(0,0,570,322));
			app_del_image(scaled_art);
			app_del_image(art);
			art_done = 1;
		}
		else {
			if (logfile)
				fprintf(logfile, "Couldn't find or load artwork file %s\n", flip->artfile);
		}
	}

	if (card->expsym[0])
		filename = card->expsym;
	else
		filename = default_expansion;
	filename = find_image_source("./", symbols, filename,
				rarity_to_trailer(filename, card->rarity));
	if (filename != NULL) {
		art = app_read_image(filename, 32);
		app_free(filename);
	}
	else
		art = NULL;

	if (art != NULL)
	{
		Rect sr = app_get_image_area(art);
		Rect dr;
		dr.y = 970;
		dr.height = 40;
		dr.width = sr.width * dr.height / sr.height;
		dr.x = full->width - 60 - dr.width;
		app_draw_image(g, dr, art, sr);
		app_del_image(art);
	}

	if (card->artist[0])
	{
		char *artcopyright = app_alloc(10 + strlen(card->artist));
		artcopyright[0] = '\0';
		//strcpy(artcopyright, "Illus. ");
		strcat(artcopyright, card->artist);

		app_set_font(g, artist_font);
		draw_white_shadow_text(g, rect(58, 950, 550, 50),
				(ALIGN_LEFT | VALIGN_CENTRE | LR_TB),
				artcopyright, (int) strlen(artcopyright));
	}

	if (card->number[0])
	{
		app_set_font(g, number_font);
		draw_white_shadow_text_1(g, rect(30, 990, full->width-60, 20),
				(ALIGN_CENTRE | VALIGN_CENTRE | LR_TB),
				card->number, (int) strlen(card->number));
	}

	app_del_graphics(g);

	return full;
}

/*
 *  Generate an image of either a normal or flipped card.
 */
Image * create_card_image_7th_ed_upright(Card *card, Colour border_colour)
{
	if (card->flip)
		return create_card_image_7th_ed_flipped(card, border_colour);
	else
		return create_card_image_7th_ed_normal(card, border_colour);
}

/*
 *  To handle split-cards (such as Fire//Ice), the following
 *  function generates two card images, and rotates them,
 *  scales them down, and blits them onto a new card image.
 *  The intermediate results are deleted and the final card
 *  image is returned.
 */
Image * create_card_image_7th_ed_split(Card *card1, Card *card2, Colour border_colour)
{
	Image *img1;
	Image *rot1;
	Image *img2;
	Image *rot2;
	Image *scaled;
	Rect ir, rr, sr;
	Graphics *g;
	const int border = 30;

	if (logfile)
		fprintf(logfile, "Viewing split-card %s // %s\n", card1->name, card2->name);

	/* Create the first card. */
	img1 = create_card_image_7th_ed_upright(card1, border_colour);
	if (img1 == NULL) /* ran out of memory */
		return NULL;
	ir = app_get_image_area(img1);
	ir = app_inset_rect(ir, border);

	/* Create the rotated version of the first card. */
	rot1 = image_32bpp_rotated_90_degrees(img1);
	app_del_image(img1); /* throw this large image away now! */
	if (rot1 == NULL) /* ran out of memory */
		return NULL;
	rr = app_get_image_area(rot1);
	rr = app_inset_rect(rr, border);

	/* Scale the rotated first card to fit into half a full card. */
	scaled = app_scale_image(rot1,
			rect(0, 0, ir.width, ir.height/2), rr);
	app_del_image(rot1); /* throw this large image away now! */
	if (scaled == NULL) /* ran out of memory */
		return NULL;
	sr = app_get_image_area(scaled);

	/* Create the second card. */
	img2 = create_card_image_7th_ed_upright(card2, border_colour);
	if (img2 == NULL) { /* ran out of memory */
		app_del_image(scaled);
		return NULL;
	}

	/* Create the rotated version of the second card. */
	rot2 = image_32bpp_rotated_90_degrees(img2);
	/* Don't throw away the second card image yet, re-use it! */
	if (rot2 == NULL) { /* ran out of memory */
		app_del_image(scaled);
		app_del_image(img2);
		return NULL;
	}

	/* Now, copy the scaled first card over the bottom half. */
	g = app_get_image_graphics(img2);
	if (g == NULL) { /* ran out of memory */
		app_del_image(scaled);
		app_del_image(img2);
		app_del_image(rot2);
		return NULL;
	}
	app_draw_image(g, rect(ir.x,
				ir.y + ir.height - sr.height,
				ir.width,
				sr.height),
			scaled, sr);
	app_del_image(scaled); /* Discard last vestige of first card. */

	/* Scale the rotated second card to fit into half a full card. */
	scaled = app_scale_image(rot2,
			rect(0, 0, ir.width/2, (ir.height+1)/2), rr);
	app_del_image(rot2); /* throw this large image away now! */
	if (scaled == NULL) { /* ran out of memory */
		app_del_image(img2);
		return NULL;
	}
	sr = app_get_image_area(scaled); /* Could be slightly taller. */

	/* Now, copy the scaled second card over the top half. */
	app_draw_image(g, rect(ir.x,
				ir.y,
				ir.width,
				sr.height),
			scaled, sr);
	app_del_image(scaled); /* Discard last vestige of second card. */

	app_del_graphics(g); /* Finished drawing now. */

	return img2;
}

/*
 *  The master function which creates a 7th Edition card image
 *  at 300 DPI from a card already parsed.
 *
 *  Note: for this function to correctly operate,
 *  the current working directory must be such
 *  that the artwork file can be found in a
 *  relative path location (unless the spoiler
 *  designated the path using an absolute path).
 *
 *  This function can handle normal cards, land etc,
 *  as well as flip cards, and split cards.
 */
Image * create_card_image_7th_ed(Card *card, Colour border_colour)
{
	if (card->split)
		return create_card_image_7th_ed_split(card, card->split, border_colour);
	else
		return create_card_image_7th_ed_upright(card, border_colour);
}
