/* 
 * Pescetti Pseudo-Duplimate Generator
 * 
 * Copyright (C) 2007 Matthew Johnson
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License Version 2 as published by
 * the Free Software Foundation.  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,
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *
 * To Contact me, please email src@matthew.ath.cx
 *
 */
package cx.ath.matthew.pescetti;

import com.lowagie.text.Cell;
import com.lowagie.text.Chunk;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Document;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.Table;
import com.lowagie.text.pdf.PdfWriter;

import cx.ath.matthew.debug.Debug;

import java.awt.Color;                                                                                       
import java.io.PrintStream;
import java.text.DecimalFormat;

public class PDFPrinter extends Printer implements Constants
{
   private PrintStream out;
   private boolean infulltable = true;
   /*private boolean inrow = false;*/
   private boolean incell = false;
   private int cellcount = 0;
   private static final int MAXCELLS = 3;
   private Document doc;
	private Table struct;
	private Table handstruct;
	private String header;
   public PDFPrinter(PrintStream out, String header)
   {
      try {
         this.out = out;
         this.doc = new Document(PageSize.A4, 20,20,30,30);
         PdfWriter.getInstance(doc, out);
			doc.addTitle(header);
			doc.open();
			Paragraph head = new Paragraph(header, new Font(Font.HELVETICA, 16, Font.BOLD));
			head.setSpacingAfter(-20);
			doc.add(head);
			struct = new Table(MAXCELLS);
			struct.setWidth(100);
			struct.setBorderColor(Color.WHITE);
			Cell c = new Cell();
			c.setBorderColor(Color.BLACK);
			struct.setDefaultLayout(c);
			this.header = header;
      } catch (DocumentException De) {
         if (Debug.debug) Debug.print(De);
      }
   }
	void newpage() throws DocumentException
	{
		if (infulltable) stopfulltable();
		doc.add(struct);
		doc.newPage();
		Paragraph head = new Paragraph(header, new Font(Font.HELVETICA, 16, Font.BOLD));
		head.setSpacingAfter(-20);
		doc.add(head);
		struct = new Table(MAXCELLS);
		struct.setWidth(100);
		struct.setBorderColor(Color.WHITE);
		Cell c = new Cell();
		c.setBorderColor(Color.BLACK);
		struct.setDefaultLayout(c);
		infulltable = true;
	}
	void stopcell() throws DocumentException
	{
		struct.insertTable(handstruct);
		incell = false;
	}
	void startcell() throws DocumentException
	{
		handstruct = new Table(3,3);
		handstruct.setWidth(100);
		handstruct.setBorderColor(new Color(0, 0, 0));
		handstruct.setBorderWidth(1);
		Cell c = new Cell();
		c.setBorderColor(Color.WHITE);
		handstruct.setDefaultLayout(c);
		incell = true;
		cellcount++;
	}
	char getDingSuit(char suit)
	{
		switch (suit) {
			case 'C': return (char) 168;
			case 'D': return (char) 169;
			case 'H': return (char) 170;
			case 'S': return (char) 171;
			default: return ' ';
		}
	}
   public void printHand(int num, byte[][] hand)
   {
		try {
			/*if (!infulltable) startfulltable();
			  if (!inrow) startrow(6);*/
			if (incell) stopcell();
			if (1  != num && 1 == num % 21) newpage();
			startcell();
			String[] printablehand = getHandPrintables(hand, SHORTSUIT);
			Cell c = new Cell(new Phrase(""+num, new Font(Font.HELVETICA, 12, Font.BOLD)));
			c.setHorizontalAlignment(Cell.ALIGN_CENTER);
			handstruct.addCell(c, 0, 0);
			StringBuilder vuln = new StringBuilder();
			vuln.append("Dlr: ");
			switch (num % 4) {
				case 1: vuln.append(PLAYER[NORTH]); break;
				case 2: vuln.append(PLAYER[EAST]); break;
				case 3: vuln.append(PLAYER[SOUTH]); break;
				case 0: vuln.append(PLAYER[WEST]); break;
			}
			vuln.append("\nVuln: ");
			switch (num % 16) {
				// ALL
				case 4:
				case 7:
				case 10:
				case 13:
					vuln.append("ALL");
					break;
					// N-S
				case 2:
				case 5:
				case 12:
				case 15:
					vuln.append("N-S");
					break;
					// E-W
				case 3:
				case 6:
				case 9:
				case 0:
					vuln.append("E-W");
					break;
					// NONE
				default:
					vuln.append("NONE");
			}
			handstruct.addCell(new Cell(new Phrase(vuln.toString(), new Font(Font.HELVETICA, 8, Font.NORMAL))), 0, 2);

			Font DINGFONT = new Font(Font.ZAPFDINGBATS, 7, Font.NORMAL);
			Font HEL = new Font(Font.HELVETICA, 7, Font.NORMAL);
			//   0 
			// 3   1
			//   2
			// NORTH;
			Phrase handstr = new Phrase(8);
			for (int i = 0; i < 4; i++) {
				char suit = getDingSuit(printablehand[i].charAt(0));
				handstr.add(new Chunk(""+suit, DINGFONT));
				handstr.add(new Chunk(printablehand[i].substring(1), HEL));
				handstr.add(new Chunk("\n", HEL));
			}
			c = new Cell(handstr);
			c.setHorizontalAlignment(Cell.ALIGN_LEFT);
			handstruct.addCell(c, 0, 1);
			
			// WEST
			handstr = new Phrase(8);
			for (int i = 4; i < 8; i++) {
				char suit = getDingSuit(printablehand[i].charAt(0));
				handstr.add(new Chunk("      "+suit, DINGFONT));
				handstr.add(new Chunk(printablehand[i].substring(1), HEL));
				handstr.add(new Chunk("\n", HEL));
			}
			c = new Cell(handstr);
			c.setHorizontalAlignment(Cell.ALIGN_LEFT);
			handstruct.addCell(c, 1, 0);
			handstruct.addCell(new Cell(), 1, 1);

			// EAST
			handstr = new Phrase(8);
			for (int i = 8; i < 12; i++) {
				char suit = getDingSuit(printablehand[i].charAt(0));
				handstr.add(new Chunk(""+suit, DINGFONT));
				handstr.add(new Chunk(printablehand[i].substring(1), HEL));
				handstr.add(new Chunk("\n", HEL));
			}
			c = new Cell(handstr);
			c.setHorizontalAlignment(Cell.ALIGN_LEFT);
			handstruct.addCell(c, 1, 2);

			// SOUTH
			handstr = new Phrase(8);
			for (int i = 12; i < 16; i++) {
				char suit = getDingSuit(printablehand[i].charAt(0));
				handstr.add(new Chunk(""+suit, DINGFONT));
				handstr.add(new Chunk(printablehand[i].substring(1), HEL));
				handstr.add(new Chunk("\n", HEL));
			}
			c = new Cell(handstr);
			c.setHorizontalAlignment(Cell.ALIGN_LEFT);
			handstruct.addCell(c, 2, 1);
		} catch (DocumentException De) {
			if (Debug.debug) Debug.print(De);
		}
   }

   public void printCurtains(int num, byte[][] hand){}
   public void printCurtainBack(int num){}
   public void printPermutation1(int num, byte[][] perm){}
   public void printPermutation(int permnum, int boardnum, byte[] perm, byte[] initperm)
   {
		try {
			Cell c = new Cell(new Phrase("Board "+boardnum+" permutation "+permnum, new Font(Font.HELVETICA, 12, Font.BOLD)));
			c.setColspan(MAXCELLS);
			struct.addCell(c);
			StringBuilder sb;
			if (null != initperm) {
				sb = new StringBuilder();
				sb.append("Order the suits: ");
				for (int i = 0; i < 4; i++) {
					sb.append(LONGSUIT[initperm[i] >> 4]);
					if (i < 3) 
						sb.append(", ");
				}
				c = new Cell(new Phrase(sb.toString(), new Font(Font.HELVETICA, 10, Font.BOLD)));
				c.setColspan(MAXCELLS);
				struct.addCell(c);
			}
			sb = new StringBuilder();
			for (int k = 0; k < 52; k++) {
				sb.append(""+(perm[k]+1));
				if (3 == k % 4)
					sb.append("    ");
				if (19 == k % 20) 
					sb.append("\n");
			}
			c = new Cell(new Phrase(sb.toString(), new Font(Font.HELVETICA, 14, Font.NORMAL)));
			c.setColspan(MAXCELLS);
			struct.addCell(c);
			if (2 == permnum && 2 == boardnum % 4) newpage();
		} catch (DocumentException De) {
         if (Debug.debug) Debug.print(De);
      }
   }

	public void stopfulltable() throws DocumentException
	{
		if (incell) stopcell();
		while (0 != cellcount % 3) {
			startcell();
			handstruct.addCell(" ");
			stopcell();
		}
		cellcount = 0;
		infulltable = false;
	}

   public void close()
   {
      /*if (incell) stopcell();
      if (inrow) stoprow();*/
		try {
			if (infulltable) stopfulltable();
			doc.add(struct);
			doc.close();
			out.close();
		} catch (DocumentException De) {
         if (Debug.debug) Debug.print(De);
      }
   }

   public void printStats(double[] stats)
   {
		try {
			DecimalFormat df = new DecimalFormat("##.##");
			if (infulltable) stopfulltable();

			Cell def = new Cell();
			def.setBorderColor(Color.WHITE);

			Table table = new Table(1);
			table.setBorderColor(Color.WHITE);
			table.setPadding(2);
			table.setDefaultLayout(def);
			table.endHeaders();

			table.addCell(new Phrase("# 4333 hands: "+(int)stats[STAT_4333], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("# Balanced hands: "+(int)stats[STAT_BAL], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("# Semi-bal hands: "+(int)stats[STAT_SEMIBAL], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("# 4441 hands: "+(int)stats[STAT_4441], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			Cell c = new Cell(table);
			struct.addCell(c);

			table = new Table(1);
			table.setBorderColor(Color.WHITE);
			table.setPadding(2);
			table.setDefaultLayout(def);
			table.endHeaders();

			table.addCell(new Phrase("# 5-5 hands: "+(int)stats[STAT_55], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("# 6+ suits: "+(int)stats[STAT_6PLUS], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("# 7+ suits: "+(int)stats[STAT_7PLUS], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("# 8+ suits: "+(int)stats[STAT_8PLUS], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			c = new Cell(table);
			struct.addCell(c);

			table = new Table(1);
			table.setBorderColor(Color.WHITE);
			table.setPadding(2);
			table.setDefaultLayout(def);
			table.endHeaders();

			table.addCell(new Phrase("# Voids: "+(int)stats[STAT_VOID], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("# Bacon hands: "+(int)stats[STAT_BACON], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			c = new Cell(table);
			struct.addCell(c);

			table = new Table(1);
			table.setBorderColor(Color.WHITE);
			table.setPadding(2);
			table.setDefaultLayout(def);
			table.endHeaders();

			table.addCell(new Phrase("North avg points: "+df.format(stats[STAT_NPOINTS]), new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("South avg points: "+df.format(stats[STAT_SPOINTS]), new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("East avg points: "+df.format(stats[STAT_EPOINTS]), new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("West avg points: "+df.format(stats[STAT_WPOINTS]), new Font(Font.HELVETICA, 10, Font.NORMAL)));
			c = new Cell(table);
			struct.addCell(c);

			table = new Table(1);
			table.setBorderColor(Color.WHITE);
			table.setPadding(2);
			table.setDefaultLayout(def);
			table.endHeaders();

			table.addCell(new Phrase("North-South games: "+(int)stats[STAT_NSGAMES], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("East-West games: "+(int)stats[STAT_NSGAMES], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("North-South slams: "+(int)stats[STAT_NSSLAMS], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			table.addCell(new Phrase("East-West slams: "+(int)stats[STAT_NSSLAMS], new Font(Font.HELVETICA, 10, Font.NORMAL)));
			c = new Cell(table);
			struct.addCell(c);

		} catch (DocumentException De) {
         if (Debug.debug) Debug.print(De);
      }
	}

   public void printTricks(byte[] tricks)
   {
      /*if (!infulltable) startfulltable();
      if (!inrow) startrow();
      if (!incell) startcell();*/
		try {
			Table table = new Table(6);
			table.setBorderColor(Color.WHITE);
			table.setPadding(0);
			Cell c = new Cell();
			c.setBorderColor(Color.WHITE);
			table.setDefaultLayout(c);
			table.addCell(new Phrase("", new Font(Font.HELVETICA, 6, Font.NORMAL)));
			c = new Cell(new Phrase(""+DINGSUIT[CLUBS>>4], new Font(Font.ZAPFDINGBATS, 6, Font.BOLD)));
			c.setHorizontalAlignment(Cell.ALIGN_CENTER);
			table.addCell(c);
			c = new Cell(new Phrase(""+DINGSUIT[DIAMONDS>>4], new Font(Font.ZAPFDINGBATS, 6, Font.BOLD)));
			c.setHorizontalAlignment(Cell.ALIGN_CENTER);
			table.addCell(c);
			c = new Cell(new Phrase(""+DINGSUIT[HEARTS>>4], new Font(Font.ZAPFDINGBATS, 6, Font.BOLD)));
			c.setHorizontalAlignment(Cell.ALIGN_CENTER);
			table.addCell(c);
			c = new Cell(new Phrase(""+DINGSUIT[SPADES>>4], new Font(Font.ZAPFDINGBATS, 6, Font.BOLD)));
			c.setHorizontalAlignment(Cell.ALIGN_CENTER);
			table.addCell(c);
			c = new Cell(new Phrase(""+DINGSUIT[NOTRUMPS>>4], new Font(Font.HELVETICA, 6, Font.BOLD)));
			c.setHorizontalAlignment(Cell.ALIGN_CENTER);
			table.addCell(c);
			table.endHeaders();

			table.addCell(new Phrase("N", new Font(Font.HELVETICA, 5, Font.BOLD)));
			for (int i = 4; i >= 0; i--) {
				c = new Cell(new Phrase(""+tricks[i], new Font(Font.HELVETICA, 5, Font.NORMAL)));
				c.setHorizontalAlignment(Cell.ALIGN_CENTER);
				table.addCell(c);
			}
			table.addCell(new Phrase("S", new Font(Font.HELVETICA, 5, Font.BOLD)));
			for (int i = 9; i >= 5; i--) {
				c = new Cell(new Phrase(""+tricks[i], new Font(Font.HELVETICA, 5, Font.NORMAL)));
				c.setHorizontalAlignment(Cell.ALIGN_CENTER);
				table.addCell(c);
			}
			table.addCell(new Phrase("E", new Font(Font.HELVETICA, 5, Font.BOLD)));
			for (int i = 14; i >= 10; i--) {
				c = new Cell(new Phrase(""+tricks[i], new Font(Font.HELVETICA, 5, Font.NORMAL)));
				c.setHorizontalAlignment(Cell.ALIGN_CENTER);
				table.addCell(c);
			}
			table.addCell(new Phrase("W", new Font(Font.HELVETICA, 5, Font.BOLD)));
			for (int i = 19; i >= 15; i--) {
				c = new Cell(new Phrase(""+tricks[i], new Font(Font.HELVETICA, 5, Font.NORMAL)));
				c.setHorizontalAlignment(Cell.ALIGN_CENTER);
				table.addCell(c);
			}
			Cell r = new Cell(table);
			r.setWidth("100");
			handstruct.addCell(r, 2, 2);
		} catch (DocumentException De) {
         if (Debug.debug) Debug.print(De);
      }
   }
   public void printPoints(byte[] points)
   {
      /*if (!infulltable) startfulltable();
      if (!inrow) startrow(6);
      if (!incell) startcell();*/
		try {
			Table table = new Table(3);
			table.setBorderColor(Color.WHITE);
			table.setPadding(0);
			Cell c = new Cell();
			c.setBorderColor(Color.WHITE);
			table.setDefaultLayout(c);
			table.endHeaders();
			c = new Cell(new Phrase(" ", new Font(Font.HELVETICA, 6, Font.NORMAL)));
			c.setColspan(3);
			table.addCell(c);
			c = new Cell(new Phrase("", new Font(Font.HELVETICA, 6, Font.NORMAL)));
			table.addCell(c);
			c = new Cell(new Phrase(""+points[NORTH], new Font(Font.HELVETICA, 6, Font.NORMAL)));
			c.setHorizontalAlignment(Cell.ALIGN_CENTER);
			table.addCell(c);
			c = new Cell(new Phrase("", new Font(Font.HELVETICA, 6, Font.NORMAL)));
			table.addCell(c);
			c = new Cell(new Phrase(""+points[WEST], new Font(Font.HELVETICA, 6, Font.NORMAL)));
			c.setHorizontalAlignment(Cell.ALIGN_RIGHT);
			table.addCell(c);
			c = new Cell(new Phrase("", new Font(Font.HELVETICA, 6, Font.NORMAL)));
			table.addCell(c);
			c = new Cell(new Phrase(""+points[EAST], new Font(Font.HELVETICA, 6, Font.NORMAL)));
			c.setHorizontalAlignment(Cell.ALIGN_LEFT);
			table.addCell(c);
			c = new Cell(new Phrase("", new Font(Font.HELVETICA, 6, Font.NORMAL)));
			table.addCell(c);
			c = new Cell(new Phrase(""+points[SOUTH], new Font(Font.HELVETICA, 6, Font.NORMAL)));
			c.setHorizontalAlignment(Cell.ALIGN_CENTER);
			table.addCell(c);
			c = new Cell(new Phrase("", new Font(Font.HELVETICA, 6, Font.NORMAL)));
			table.addCell(c);
			Cell r = new Cell(table);
			r.setVerticalAlignment(Cell.ALIGN_MIDDLE);
			handstruct.addCell(r, 2, 0);
		} catch (DocumentException De) {
         if (Debug.debug) Debug.print(De);
      }
   }
   public void println(String s)
   {
   }
   public void print(String s)
   {
   }
}

