package controler.facture;

import java.awt.Desktop;
import java.io.File;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Date;
import java.sql.Time;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import rapport.RapportFacture;
import language.Language;
import view.vueFacture.VueFacture;
import view.vueGestionArticle.VueGestionAjouterArticle;
import view.vueGestionArticle.VueGestionModifierArticle;
import view.vuePopup.PopupFacturePaiement.paiement;
import commander.Commander;
import controler.Message;
import database.crud.ArticleCrud;
import database.crud.ChambreCrud;
import database.crud.EncaissementCrud;
import database.crud.FactureCrud;
import database.crud.ModePaiementCrud;
import database.crud.TaxeCrud;
import database.crud.denormalised.ViewEncaissementCrud;
import database.crud.denormalised.ViewFactureCrud;
import database.crud.denormalised.ViewVenteCrud;
import database.crud.reservation.ReservationCrud;
import database.crud.vente.VenteArticleCrud;
import database.crud.vente.VenteCrud;
import database.dataset.Article;
import database.dataset.Chambre;
import database.dataset.Encaissement;
import database.dataset.Facture;
import database.dataset.Modedepaiement;
import database.dataset.Reservation;
import database.dataset.Taxe;
import database.dataset.Vente;
import database.dataset.Vente_article;
import database.migration.SqlFactory;

public class ControlerFacture {
	public static final Message reveil = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			VueFacture vue = (VueFacture)caster;
			Connection connection = Commander.getInstance().getConnectionBD();
				
			if(vue.getFacture_id() == 0)
			{
				vue.setEnabled(false);
			}
			else
			{
				vue.setEnabled(true);
			}
		}
	};
	

	public static final Message selectioner = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			//VueFacture vue = (VueFacture)caster;

			Language lang = Commander.getInstance().getLanguage();
			Commander.getInstance().getVuePrincipale().setSelectedTab(lang.getPrincipaleRecherche(), lang.getRechercheClient());
		}
	};
	

	public static final Message annuler = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			VueFacture vue = (VueFacture)caster;
			Connection connection = Commander.getInstance().getConnectionBD();
			
			vue.setEnabled(false);
			
			Language lang = Commander.getInstance().getLanguage();
			Commander.getInstance().getVuePrincipale().setModifiedTab(lang.getPrincipaleReception(), lang.getReceptionFacture(),false);
		}
	};
	
	
	public static final Message checkin = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			VueFacture vue = (VueFacture)caster;
			Connection connection = Commander.getInstance().getConnectionBD();
			ReservationCrud reservationCrud = new ReservationCrud(connection);
			
			for(int i =0;i<vue.getSize_ReservationId();i++){
				if(vue.getCheckBoxValueAtTableReservation(i)){
					reservationCrud.updateCheckInCheckOut(vue.get_ReservationIdItem(i), 3);
				}
			}
		}
	};
	

	public static final Message checkout = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			VueFacture vue = (VueFacture)caster;
			Connection connection = Commander.getInstance().getConnectionBD();
			ReservationCrud reservationCrud = new ReservationCrud(connection);
			
			for(int i =0;i<vue.getSize_ReservationId();i++){
				if(vue.getCheckBoxValueAtTableReservation(i)){
					reservationCrud.updateCheckInCheckOut(vue.get_ReservationIdItem(i), 3);
				}
			}
		}
	};
	

	public static final Message imprimer = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			VueFacture vue = (VueFacture)caster;

			Connection connection = Commander.getInstance().getConnectionBD();

			RapportFacture rapport = new RapportFacture();

			String sqlFacture = "SELECT * FROM view_facture WHERE facture_p_id="+vue.getFacture_id();
			String sqlVente = "SELECT * FROM view_vente LEFT JOIN reservation ON reservation_p_id=reservation_fk_id WHERE facture_fk_id="+vue.getFacture_id();
			String sqlTotal = "SELECT SUM(sous_total)+SUM(tps)+SUM(tvq)+SUM(hebergement) AS total, SUM(sous_total) AS sous_total,SUM(tps) AS tps,SUM(tvq) AS tvq,SUM(hebergement) AS hebergement "+
			"FROM view_vente_total WHERE facture_fk_id="+vue.getFacture_id()+"  GROUP BY facture_fk_id ";
		
			for(Map<String,Object> row: SqlFactory.query(connection, sqlFacture)){
				rapport.setNumeroFacture(vue.getFacture_id());
				rapport.setPictureFile("logo.png");
				
				rapport.setAdresseClient(row.get("adresse_no_rue_app").toString());
				rapport.setCodepostalClient(row.get("adresse_codepostal").toString());
				rapport.setCommentaire(row.get("facture_commentaire").toString());
				rapport.setNomClient(row.get("client_nom").toString()+" "+row.get("client_prenom").toString());
				rapport.setVilleProvClient(row.get("ville_nom").toString());
				
				for (Map<String,Object> rowTotal: SqlFactory.query(connection, sqlTotal)){
					rapport.setSoustotal((BigDecimal)rowTotal.get("sous_total"));
					rapport.setTotal((BigDecimal)rowTotal.get("total"));
					rapport.setTps((BigDecimal)rowTotal.get("tps"));
					rapport.setTvq((BigDecimal)rowTotal.get("tvq"));
				}
				
				for (Map<String,Object> rowVente: SqlFactory.query(connection, sqlVente))
					rapport.add((Date)rowVente.get("vente_jour"), 
								rowVente.get("chambre_fk_id"), 
								rowVente.get("article_description").toString(), 
								((Long)rowVente.get("quantite")).intValue(), 
								(BigDecimal)rowVente.get("vente_prix"), 
								/*(BigDecimal)rowVente.get("")*/new BigDecimal(0));
				
				rapport.generate();
				
				String rapportName = "facture_"+vue.getFacture_id()+".pdf";
				
				rapport.getDocument().save(rapportName);
				rapport.getDocument().close();
			    File myFile = new File(rapportName);
			    Desktop.getDesktop().open(myFile);
			}
		}
	};
	

	public static final Message paiement = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			VueFacture vue = (VueFacture)caster;
			
			if(vue.getFacture_id() == 0)
				return;
			
			Connection connection = Commander.getInstance().getConnectionBD();
			
			Facture facture = new Facture(vue.getFacture_id(), 0, 0, null, 0, null, null, null);
			ViewVenteCrud viewVenteCrud = new ViewVenteCrud(connection);
			ViewEncaissementCrud viewencaissementCrud = new ViewEncaissementCrud(connection);
			EncaissementCrud encaissementCrud = new EncaissementCrud(connection); 
			
			Map<String, BigDecimal> totalMap = viewVenteCrud.getSumVenteFromFacture(facture.getFacture_p_id());
			
			BigDecimal total = BigDecimal.ZERO;
			BigDecimal present = viewencaissementCrud.getSumEncaissementFromFacture(facture.getFacture_p_id(),"");
			BigDecimal balance;
			
			for(BigDecimal money : totalMap.values())
			{
				total = total.add(money);
			}
			
			if(present == null)
			{
				balance = total;
				present = BigDecimal.ZERO;
			}
			else
			{
				balance = total.subtract(present);
			}
			
			ModePaiementCrud modepaiementCrud = new ModePaiementCrud(connection);
			List<Modedepaiement> modes = modepaiementCrud.readAll();
			String[] modePaiement = new String[modes.size()];
			for(int i = 0; i < modes.size(); i++)
				modePaiement[i] = modes.get(i).getModedepaiement_nom();

			paiement paie = vue.getMontantNewPaiement(present, balance, total, modePaiement);
			BigDecimal montantValue = new BigDecimal(paie.montant.substring(0,paie.montant.length()-1));
			int id_modedepaiement = modepaiementCrud.readByNom(paie.methodePaiement).getmodedepaiement_p_id();
			
			if(montantValue == BigDecimal.ZERO)
			{
				return;
			}
			if(id_modedepaiement == 0)
			{
				return;
			}
			
			Encaissement encaissement = new Encaissement(encaissementCrud.getNewSequenceId(), vue.getFacture_id(), id_modedepaiement, montantValue);
			encaissementCrud.create(encaissement);
		}
	};
	
	public static final Message enregistrer = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			VueFacture vue = (VueFacture)caster;
			Connection connection = Commander.getInstance().getConnectionBD();
			
			BigDecimal totalFacture = BigDecimal.ZERO,
					   sousTotal,
					   total,
					   tps,
					   tvq;
			
			VenteArticleCrud venteArticleCrud = new VenteArticleCrud(connection);
			ArticleCrud articleCrud = new ArticleCrud(connection);
			ReservationCrud reservationCrud = new ReservationCrud(connection);
			VenteCrud venteCrud = new VenteCrud(connection);
			TaxeCrud taxeCrud = new TaxeCrud(connection);
			ChambreCrud chambreCrud = new ChambreCrud(connection); 
			
			Vente vente;
			Reservation reservation;
			Chambre chambre;
			Vente_article vente_article;
			List<Article> article = new ArrayList<Article>();
			
			for(int i=0;i<vue.getSize_ReservationVenteId();i++)
			{
				article = articleCrud.readAllLike(vue.getPromotionValueAtTableReservation(i), "", "", "", "");
				vente = new Vente(vue.get_ReservationVenteIdItem(i), new Time(System.currentTimeMillis()), new Date(System.currentTimeMillis()), vue.getPrixValueAtTableReservation(i), vue.getFacture_id(), article.get(0).getarticle_p_id());
				
				Taxe taxe = taxeCrud.readLast();
				tps = ((vue.getPrixValueAtTableReservation(i).multiply(taxe.getTaxe_tps())));
				tvq = ((vue.getPrixValueAtTableReservation(i).add(tps)).multiply(taxe.getTaxe_tvq()));
				total = (vue.getPrixValueAtTableReservation(i).add(tps)).add(tvq);
				totalFacture = totalFacture.add(total);
				
				vue.setTPSValueAtTableReservation(i, tps);
				vue.setTVQValueAtTableReservation(i, tvq);
				vue.setTotalValueAtTableReservation(i, total);
				
				venteCrud.update(vente);
				
				if(vue.get_ReservationIdItem(i) != 0)
				{
					reservation = reservationCrud.readById(vue.get_ReservationIdItem(i));
					chambre = chambreCrud.readByNumero(vue.getChambreValueAtTableReservation(i));
					
					reservation = new Reservation(vue.get_ReservationIdItem(i), chambre.getChambre_p_id(), vue.getDateDebutValueAtTableReservation(i), vue.getDateFinValueAtTableReservation(i), reservation.getReservation_commentaire(), reservation.getStatus_fk_id());
					reservationCrud.update(reservation);
				}
			}
			
			for(int i=0; i<vue.getSize_VenteId();i++)
			{
				article = articleCrud.readAllLike(vue.getArticleSelectedAtTableVente(i), "", "", "", "");
				vente_article = new Vente_article(vue.get_VenteIdItem(i), new Time(System.currentTimeMillis()), new Date(System.currentTimeMillis()), vue.getPrixValueAtTableVente(i), vue.getFacture_id(), article.get(0).getarticle_p_id(), vue.getNombreAtTableVente(i));
				venteArticleCrud.update(vente_article);
				
				Taxe taxe = taxeCrud.readLast();
				tps = ((vue.getPrixValueAtTableVente(i).multiply(new BigDecimal(vue.getNombreAtTableVente(i)))).multiply(taxe.getTaxe_tps()));
				tvq = ((vue.getPrixValueAtTableVente(i).multiply(new BigDecimal(vue.getNombreAtTableVente(i)))).add(tps)).multiply(taxe.getTaxe_tvq());
				sousTotal = (vue.getPrixValueAtTableVente(i).multiply(new BigDecimal(vue.getNombreAtTableVente(i))));
				total = ((vue.getPrixValueAtTableVente(i).multiply(new BigDecimal(vue.getNombreAtTableVente(i)))).add(tps)).add(tvq);
				totalFacture = totalFacture.add(total);
				
				vue.setSousTotalValueAtTableVente(i, sousTotal);
				vue.setTPSValueAtTableVente(i, tps);
				vue.setTVQValueAtTableVente(i, tvq);
				vue.setTotalValueAtTableVente(i, total);
				
			}
			
			vue.setTotal(totalFacture);
			
			Language lang = Commander.getInstance().getLanguage();
			Commander.getInstance().getVuePrincipale().setModifiedTab(lang.getPrincipaleReception(), lang.getReceptionFacture(),false);
		}
	};
	
	public static final Message creerVente = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			VueFacture vue = (VueFacture)caster;
			Connection connection = Commander.getInstance().getConnectionBD();
			
			VenteCrud venteCrud = new VenteCrud(connection);
			ArticleCrud articleCrud = new ArticleCrud(connection);
			VenteArticleCrud venteArticleCrud = new VenteArticleCrud(connection);
			
			Vente_article vente_article = new Vente_article(venteCrud.getNewSequenceId(), new Time(System.currentTimeMillis()), new Date(System.currentTimeMillis()), new BigDecimal(0), vue.getFacture_id(), 20, 0);
			
			List<Article> articleDepanneur = articleCrud.readByFk_categorie(3);
			List<Article> articleRestaurant = articleCrud.readByFk_categorie(4);
			List<Article> articleAdministration = articleCrud.readByFk_categorie(5);
			
			List<Article> article = new ArrayList<Article>();
			for(int i=0;i<articleDepanneur.size();i++)
			{
				if(articleDepanneur.get(i).isArticle_actif())
				{
					article.add(articleDepanneur.get(i));
				}				
			}
			for(int i=0;i<articleRestaurant.size();i++)
			{
				if(articleRestaurant.get(i).isArticle_actif())
				{
					article.add(articleRestaurant.get(i));
				}
			}
			for(int i=0;i<articleAdministration.size();i++)
			{
				if(articleAdministration.get(i).isArticle_actif())
				{
					article.add(articleAdministration.get(i));
				}
			}
			venteArticleCrud.create(vente_article);
			vue.addRowTableVenteWithArticle(new Date(System.currentTimeMillis()).toString(), article, 0);
			vue.add_VenteId(vente_article.getVente_p_id());
			vue.updateUI();
		}
	};
	
	public static final Message dataChanged = new Message(){
		public void trigger(Object caster) throws Exception {
			if (!(caster instanceof VueFacture))
				return;
			
			Language lang = Commander.getInstance().getLanguage();
			Commander.getInstance().getVuePrincipale().setModifiedTab(lang.getPrincipaleReception(), lang.getReceptionFacture(),true);	
		}
	};
}
