package rapport;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.io.RandomAccessFile;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDCcitt;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;

/**
 * basic portrait document
 * @author martin
 *
 */
public abstract class Rapport {
	/*properties*/
	protected PDDocument document;
	protected PDPage page;
	protected int nPage;

	/**
	 * constructor
	 * @throws IOException
	 */
	public Rapport() throws IOException{
		document = new PDDocument();
		page = new PDPage(PDPage.PAGE_SIZE_LETTER);
		document.addPage(page);
		nPage=1;
	}
	
	/**
	 * change page
	 * @throws IOException
	 */
	public void nextPage() throws IOException{
		page = new PDPage(PDPage.PAGE_SIZE_LETTER);
		document.addPage(page);
		nPage++;
	}
	
	/**
	 * tel current page
	 * @return
	 */
	public int currentPage(){
		return nPage;
	}
	
	/**
	 * determinate count of page from implementation
	 * @return int
	 */
	public abstract int countPage();
	
	/**
	 * build header from first page
	 * @throws IOException
	 */
	public abstract void firstPageHeader() throws IOException;

	/**
	 * build the header that come to every page
	 * @throws IOException
	 */
	public abstract void header() throws IOException;

	/**
	 * build footer that come to every page
	 * @throws IOException
	 */
	public abstract void footer() throws IOException;

	/**
	 * build the footer from the last page
	 * @throws IOException
	 */
	public abstract void lastPageFooter() throws IOException;

	/**
	 * build the body of the document
	 * @throws IOException
	 */
	public abstract void body() throws IOException;
	
	/**
	 * the whole document is generated here
	 * @throws IOException
	 */
	public abstract void generate() throws IOException;
	
	/**
	 * return the document
	 * @return PDDocument
	 */
	public PDDocument getDocument(){
		return document;
	}
	
	/**
	 * return the width of the document in pixel
	 * @return
	 */
	public float getW(){
		return page.getArtBox().getWidth();
	}
	
	/**
	 * return le height of the document in pixel
	 * @return
	 */
	public float getH(){
		return page.getArtBox().getHeight();
	}
	
	/**
	 * put text centered on given coordinate
	 * @param text as String
	 * @param font as PDFont
	 * @param size as int size of the font
	 * @param x as the position where text is centered
	 * @param y
	 * @throws IOException
	 */
	public void addText(String text, PDFont font, int size, float x, float y) throws IOException{
		PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
		float textW = font.getStringWidth(text)/1000 * size;
		float textH = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * size;
		y = getH()-y;

		contentStream.beginText();
		contentStream.setFont( font, size );
		contentStream.moveTextPositionByAmount( x - textW/2, y - textH/2 );
		contentStream.drawString(text);
		contentStream.endText();
		contentStream.close();
	}
	
	/**
	 * put text left aligned where bounding box is centered as give coordinate
	 * @param text as String
	 * @param font as PDFont
	 * @param size as int size of the font
	 * @param x as the position where the bounding box is centered
	 * @param y
	 * @param numcharmax as number of character the bounding box is sized
	 * @throws IOException
	 */
	public void addTextLeftAlign(String text, PDFont font, int size, float x, float y, int numcharmax) throws IOException{
		PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
		float textW = font.getStringWidth(text)/1000 * size;
		float textH = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * size;
		float boxW = font.getAverageFontWidth()*numcharmax/900 * size;
		y = getH()-y;

		contentStream.beginText();
		contentStream.setFont( font, size );
		contentStream.moveTextPositionByAmount( x - boxW/2, y - textH/2 );
		contentStream.drawString(text);
		contentStream.endText();
		contentStream.close();
	}

	/**
	 * put text right aligned where bounding box is centered as give coordinate
	 * @param text as String
	 * @param font as PDFont
	 * @param size as int size of the font
	 * @param x as the position where the bounding box is centered
	 * @param y
	 * @param numcharmax as number of character the bounding box is sized
	 * @throws IOException
	 */
	public void addTextRightAlign(String text, PDFont font, int size, float x, float y, int numcharmax) throws IOException{
		PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
		float textW = font.getStringWidth(text)/1000 * size;
		float textH = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * size;
		float boxW = font.getAverageFontWidth()*numcharmax/900 * size;
		y = getH()-y;

		contentStream.beginText();
		contentStream.setFont( font, size );
		contentStream.moveTextPositionByAmount( x + boxW-textW, y - textH/2 );
		contentStream.drawString(text);
		contentStream.endText();
		contentStream.close();
	}
	
	/**
	 * put text in a box where bounding box is centered as give coordinate
	 * @param text as String
	 * @param font as PDFont
	 * @param size as int size of the font
	 * @param x as the position where the bounding box is centered
	 * @param y
	 * @param numcharmax as number of character the bounding box is sized
	 * @throws IOException
	 */
	public void addTextInBox(String text, PDFont font, int size, float x, float y, int numcharmax) throws IOException{
		PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
		y = getH()-y;
		float textW = font.getStringWidth(text)/1000 * size;
		float textH = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * size;
		float boxW = font.getAverageFontWidth()*numcharmax/1000 * size;
		float boxH = textH * 1.1f;
		
		contentStream.beginText();
		contentStream.setFont( font, size );
		contentStream.moveTextPositionByAmount( x - textW/2, y - textH/2 );
		contentStream.drawString(text);
		contentStream.endText();

		//contentStream.addRect(x - boxW/2, y-boxH * 0.7f, boxW, boxH);
		contentStream.close();
		
		addBox(x, getH()-y+2,boxW, boxH);
	}
	
	/**
	 * put box centered at given coordinate, sized given size
	 * @param x as coordinate
	 * @param y
	 * @param w as size
	 * @param h
	 * @throws IOException
	 */
	public void addBox(float x, float y, float w, float h) throws IOException{
		PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
		y = getH()-y;
		contentStream.drawLine(x-w/2, y-h/2, x+w/2, y-h/2);
		contentStream.drawLine(x-w/2, y+h/2, x+w/2, y+h/2);
		contentStream.drawLine(x+w/2, y+h/2, x+w/2, y-h/2);
		contentStream.drawLine(x-w/2, y+h/2, x-w/2, y-h/2);
		contentStream.close();
	}
	
	/**
	 * put a separator line full dicument width
	 * @param height
	 * @throws IOException
	 */
	public void addSeparator(float height) throws IOException{
		PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
		contentStream.drawLine(0, getH()-height, getW(), getH()-height);
		contentStream.close();
	}
	
	/**
	 * put line at given heigth and given width
	 * @param x
	 * @param length
	 * @param height
	 * @throws IOException
	 */
	public void addLine(float x, float length, float height) throws IOException{
		PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
		contentStream.drawLine(x, getH()-height, x+length, getH()-height);
		contentStream.close();
	}
	
	/**
	 * put image at given coordinate
	 * this method position image by its corner
	 * @param jpegfilename as String
	 * @param x as coordinate
	 * @param y
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public void addImage(String jpegfilename,float x,float y) throws FileNotFoundException, IOException{
        PDXObjectImage image = new PDJpeg(document, new FileInputStream( jpegfilename ) );

        PDPageContentStream contentStream = new PDPageContentStream(document, page);

        contentStream.drawImage(image, x, getH()-y-image.getHeight());

        contentStream.close();
	}
	
	/**
	 * put vertical text
	 * this method position text by bottom center
	 * so it can sit next to horizontal text
	 * @param text as String
	 * @param font as PDFont
	 * @param size as font size
	 * @param x as coordinate
	 * @param y
	 * @throws IOException
	 */
	public void addVerticalText(String text, PDFont font, int size, float x, float y) throws IOException{
		PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
		float textW = font.getStringWidth(text)/1000 * size;
		float textH = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * size;
		y = getH()-y;

		contentStream.beginText();
		contentStream.setFont( font, size );
		//contentStream.moveTextPositionByAmount( x - textW/2, y - textH/2 );
		contentStream.setTextRotation(1.57079, x+size/2, y-size/2);
		contentStream.drawString(text);
		contentStream.endText();
		contentStream.close();
	}

	/**
	 * simply save the document
	 * @param file as String
	 * @throws COSVisitorException
	 * @throws IOException
	 */
	public void saveas(String file) throws COSVisitorException, IOException{
		getDocument().save(file);
	}
}
