package rapport;
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

/**
 * rapport facture
 * pdf bill generator
 * @author martin
 *
 */
public class RapportFacture extends Rapport {
	private static class Row{
		public Date dateVente;
		public int numeroChambre;
		public String description;
		public int quantite;
		public BigDecimal prix;
		public BigDecimal soustotal;
		private Row(Date dateVente, int numeroChambre, String description,
				int quantite, BigDecimal prix, BigDecimal soustotal) {
			super();
			this.dateVente = dateVente;
			this.numeroChambre = numeroChambre;
			this.description = description;
			this.quantite = quantite;
			this.prix = prix;
			this.soustotal = soustotal;
		}
	};
	
	private String nomClient;
	private String adresseClient;
	private String villeProvClient;
	private String codepostalClient;
	private int numeroFacture;
	
	private String pictureFile;
	
	private List<Row> venteLst;
	
	private BigDecimal soustotal;
	private BigDecimal tvq;
	private BigDecimal tps;
	private BigDecimal total;
	private String commentaire;
	
	private int cursor;
	private PDFont bold;
	private PDFont font;
	
	/**
	 * constructor
	 * @throws IOException
	 */
	public RapportFacture() throws IOException {
		super();
		this.nomClient = "";
		this.adresseClient = "";
		this.villeProvClient = "";
		this.codepostalClient = "";
		this.numeroFacture = 0;
		this.venteLst=new ArrayList<>();
		this.soustotal=new BigDecimal("0");
		this.tvq=new BigDecimal("0");
		this.tps=new BigDecimal("0");
		this.total=new BigDecimal("0");
		this.commentaire="un message de la shop";
		
		this.pictureFile="";
		
		cursor=0;
		bold = PDType1Font.HELVETICA_BOLD;
		font = PDType1Font.HELVETICA;
	}

	@Override
	public int countPage() {
		return venteLst.size()/27+(venteLst.size()%27==0?0:1);
	}

	@Override
	public void firstPageHeader() throws IOException {

	}

	@Override
	public void header() throws IOException {
		if (!pictureFile.equals(""))
			addImage(pictureFile, 0, 0);
		addTextRightAlign("Facture", bold, 12, getW()-200, 54, 7);
		addTextInBox(""+numeroFacture, font, 12, getW()-100, 54,8);
		
		addTextLeftAlign("Nom", bold, 12, 120 , 156,30);
		addTextLeftAlign("Adresse", bold, 12, 120 , 168,30);
		addTextLeftAlign("Ville et province", bold, 12, 120 , 180,30);
		addTextLeftAlign("Code Postal", bold, 12, 120 , 192,30);
		
		addTextLeftAlign(nomClient, font, 12, 240+(getW()-240)/2 , 156,70);
		addTextLeftAlign(adresseClient, font, 12, 240+(getW()-240)/2 , 168,70);
		addTextLeftAlign(villeProvClient, font, 12, 240+(getW()-240)/2 , 180,70);
		addTextLeftAlign(codepostalClient, font, 12, 240+(getW()-240)/2 , 192,70);
		
		addSeparator(220);
		addTextLeftAlign("Date", bold, 12, 63, 210,15);
		addText("Chambre",bold,12,90,210);
		addTextLeftAlign("Description", bold, 12, getW()/2, 210, 40);
		addText("Quantité",bold,12,getW()-150,210);
		addTextRightAlign("Prix",bold,12,getW()-150,210,10);
		addTextRightAlign("Sous-Total",bold,12,getW()-80,210,10);
	}
	
	@Override
	public void body() throws IOException {
		int n = 27<venteLst.size()-cursor?27:venteLst.size()-cursor;
		for (int y=0;y<n;y++){
			Row row = venteLst.get(cursor+y);
			addTextLeftAlign(row.dateVente.toString(), font, 10, 52, 230+y*18,15);
			addText(""+row.numeroChambre,font,12,90,230+y*18);
			if (row.description.length()>65)
				row.description=row.description.substring(0, 62)+"...";
			addTextLeftAlign(row.description, font, 10, getW()/2, 230+y*18, 50);
			addText(""+row.quantite,font,12,getW()-150,230+y*18);
			addTextRightAlign(row.prix.toPlainString()+"$",font,12,getW()-150,230+y*18,10);
			addTextRightAlign(row.prix.multiply(BigDecimal.valueOf(row.quantite)).toPlainString()+"$",font,12,getW()-80,230+y*18,10);
		}
		cursor+=27;
	}

	@Override
	public void footer() throws IOException {
		addTextRightAlign("Page "+(cursor/27+(cursor%27==0?0:1))+" de "+countPage(), bold, 12, getW()-130, getH()-8, 16);
	}

	@Override
	public void lastPageFooter() throws IOException {
		
		addTextRightAlign("Total", bold, 12, getW()-82, getH()-72, 10);
		addTextRightAlign("TVQ", bold, 12, getW()-142, getH()-72, 10);
		addTextRightAlign("TPS", bold, 12, getW()-202, getH()-72, 10);
		addTextRightAlign("Sous-Total", bold, 12, getW()-262, getH()-72, 10);

		addText(total.toPlainString()+"$", font, 12, getW()-36, getH()-57);
		addBox(getW()-36, getH()-54, 60, 14);
		addText(tvq.toPlainString()+"$", font, 12, getW()-96, getH()-57);
		addBox(getW()-96, getH()-54, 60, 14);
		addText(tps.toPlainString()+"$", font, 12, getW()-156, getH()-57);
		addBox(getW()-156, getH()-54, 60, 14);
		addText(soustotal.toPlainString()+"$", font, 12, getW()-216, getH()-57);
		addBox(getW()-216, getH()-54, 60, 14);
		
		addSeparator(getH()-80);
		
		addTextLeftAlign("Signature:", bold, 12, (getW()-276)/2, getH()-57, 40);
		addLine(82, 240, getH()-50);
		
		if (commentaire.length()>100){
			addTextLeftAlign(commentaire.substring(0,100), font, 10, getW()/2, getH()-36, 100);
			addTextLeftAlign(commentaire.substring(100,200), font, 10, getW()/2, getH()-24, 100);
		}else
			addTextLeftAlign(commentaire, font, 10, getW()/2, getH()-36, 100);
	}

	@Override
	public void generate() throws IOException {
		firstPageHeader();
		boolean notlastpage=true;
		while (notlastpage){
			header();
			body();
			footer();
			notlastpage = cursor<venteLst.size();
			if (notlastpage)
				nextPage();
		}
		lastPageFooter();
	}
	
	/**
	 * set the picture to put on top left corner of the bill
	 * @param pictureFile as file name
	 */
	public void setPictureFile(String pictureFile) {
		this.pictureFile = pictureFile;
	}

	/**
	 * set name of the costumer
	 * @param nomClient
	 */
	public void setNomClient(String nomClient) {
		this.nomClient = nomClient;
	}

	/**
	 * set adress of the costumer
	 * @param adresseClient
	 */
	public void setAdresseClient(String adresseClient) {
		this.adresseClient = adresseClient;
	}

	/**
	 * set the city the costumer is living
	 * @param villeProvClient
	 */
	public void setVilleProvClient(String villeProvClient) {
		this.villeProvClient = villeProvClient;
	}

	/**
	 * set zip code of the costumer
	 * @param codepostalClient
	 */
	public void setCodepostalClient(String codepostalClient) {
		this.codepostalClient = codepostalClient;
	}

	/**
	 * set the bill id
	 * @param numeroFacture
	 */
	public void setNumeroFacture(int numeroFacture) {
		this.numeroFacture = numeroFacture;
	}

	/**
	 * set the sub total before tax
	 * @param soustotal
	 */
	public void setSoustotal(BigDecimal soustotal) {
		this.soustotal = soustotal;
	}

	/**
	 * set the provincial tax amount
	 * @param tvq
	 */
	public void setTvq(BigDecimal tvq) {
		this.tvq = tvq;
	}

	/**
	 * set the federal tax amount
	 * @param tps
	 */
	public void setTps(BigDecimal tps) {
		this.tps = tps;
	}

	/**
	 * set the total including tax
	 * @param total
	 */
	public void setTotal(BigDecimal total) {
		this.total = total;
	}

	/**
	 * set bill comment if necessary
	 * message from the shop
	 * @param commentaire
	 */
	public void setCommentaire(String commentaire) {
		this.commentaire = commentaire;
	}

	/**
	 * add new sell to bill in
	 * @param dateVente     as date
	 * @param numeroChambre as room number
	 * @param description   as description
	 * @param quantite      as quantity of unit
	 * @param prix          as price for one unit
	 * @param soustotal     as sum of price
	 * @return true if success
	 */
	public boolean add(Date dateVente, int numeroChambre, String description,
			int quantite, BigDecimal prix, BigDecimal soustotal) {
		return venteLst.add(new Row(dateVente, numeroChambre, description, quantite, prix, soustotal));
	}

	public static void main(String...arg) throws IOException, COSVisitorException{
		RapportFacture rapport = new RapportFacture();
		
		rapport.setAdresseClient("2020 du finfin");
		rapport.setCodepostalClient("hohoho");
		rapport.setCommentaire("C'est le pere noel");
		rapport.setNomClient("Santa Claus");
		rapport.setNumeroFacture(1);
		for (int i=0;i<29;i++)
			rapport.add(new Date(0), 237, 
					    "Le petit reine au nez rooouuuggeee aaaah comme il était mignon, avec son pti nez rougeeeee", 
					    1, new BigDecimal(10), new BigDecimal(10));
		
		rapport.generate();
		
		rapport.getDocument().save("test.pdf");
		rapport.getDocument().close();
	    File myFile = new File("test.pdf");
	    Desktop.getDesktop().open(myFile);
	}
}
