package driver;
import com.sun.jna.platform.FileUtils;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.Native;
import java.applet.Applet; 
import java.applet.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.*;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.*;
import java.util.*;

import com.sun.comm.*;
import com.sun.corba.se.impl.ior.ByteBuffer;

import java.lang.*;

import gnu.io.*;

import org.apache.commons.lang.StringUtils;

public class BemaDriver {	
	
	private String rif;
	private String nombre;
	private String direccion;
	private String nombrerif;
	private JSONArray itemsArray;
	private String IncrementoDescuento;
	private String TipoIncDesc;
	private String ValorIncremento;
	private String ValorDescuento;
	
	private String FormaPago;
	private String ValorPago;
	private String NumeroPartesPago;
	private String MsjPago;
	private String MsjCierre;
	private String nrocupon;
	private int ActivaGuill;
	
	private CommPortIdentifier selectedPortIdentifier = null;
    private SerialPort serialPort = null;
    private Enumeration portList;
    private HashMap portMap = new HashMap();
    private String puerto = "COM1";
    private int baudRate = 9600;
         
	public BemaDriver(){
		System.load("C:/Windows/SysWOW64/BemaFI32.dll");
	}	
  
	public interface Bematech extends StdCallLibrary {  
	   int	Bematech_FI_VerificaFormasPago( byte[] resp );	   
	   int	Bematech_FI_NumeroCupon(String nrocupon);
	   int	Bematech_FI_RetornoAliquotas( byte[] resp );
	   int	Bematech_FI_SimboloMoneda( byte[] resp );
	   int  Bematech_FI_RetornoImpressoraMFD( int ack, int st1, int st2, int st3 );
	   int  Bematech_FI_VerificaEstadoImpresora( byte[] ack, byte[] st1, byte[] st2);	   
	   int  Bematech_FI_AbreCupon(String nombrerif);
	   int  Bematech_FI_ModeloVersionImpresora(String modelo, String version);
	   int  Bematech_FI_AbreCupom(String rif);
	   int  Bematech_FI_SubTotalizaCupomMFD();
	   int  Bematech_FI_TotalizaCupomMFD();	   
	   int  Bematech_FI_AtivaDesativaGuilhotinaMFD(int ActiviGuillotina);
	   int  Bematech_FI_VendeItemDepartamento(String cCodigo, String cDescricao, String cAliquota, String cValor, String cQtde, String cAcresc, String cDesc, String cIndice, String cUnidade);
	   int  Bematech_FI_VendeItemArredondamentoMFD(String codigo, String descripcion, String aliquota, String UnidadeMedida, String Cantidad, String ValorUnitario, String IncrementoPorcentual, String DescuentoPorcentual, boolean Redondear);
	   int  Bematech_FI_VendeItem(String codigo, String descripcion, String aliquota, String TipoCantidad,String Cantidad,int NroDecimales,String ValorUnitario,String TipoDescuento,String ValorDesc);
	   int  Bematech_FI_IniciaFechamentoCupomMFD(String IncrementoDescuento,String TipoIncDesc,String ValorIncremento,String ValorDescuento);
	   int  Bematech_FI_IniciaCierreCupon(String IncrementoDescuento,String TipoIncDesc,String ValorIncremento);
	   int  Bematech_FI_EfetuaFormaPagamentoIndiceMFD(String IncrementoDescuento,String TipoIncDesc,String ValorIncremento,String ValorDescuento);	   
	   int  Bematech_FI_EfetuaFormaPagamentoMFD(String FormaPago,String ValorPago,String NumeroPartesPago,String MsjPago);
	   int  Bematech_FI_EfectuaFormaPago(String FormaPago,String ValorPago);	   
	   int  Bematech_FI_FinalizarCierreCupon(String MsjCierre);
	   int  Bematech_FI_FinalizarCierreCuponCodigoBarrasMFD(String cMensagem,String cTipoCodigo,String cCodigo,int iAltura,int iLargura,int iPosicaoCaracteres,int iFonte,int iMargem,int iCorrecaoErros,int iColunas);
	   
	   Bematech lib = (Bematech) Native.loadLibrary("BemaFI32", Bematech.class);
	}  
   
   public static void main(String[] parametro) throws JSONException, PortInUseException, IOException {
	   
	   BemaDriver Clase;
	   Clase=new BemaDriver();
	   boolean resp = true;
	   //Clase.RetornoAliquotas();
	   //Clase.FormasDePago();
	   //Clase.SimboloMoneda();	
	   
	   Clase.rif = "J-29811494-0";
	   Clase.nombre = "REPRESENTACIONES COVENSOL C.A.";
	   Clase.direccion = "AVE. PANTEÓN";
	   
	   Clase.nombre = StringUtils.rightPad(Clase.nombre, 41, " ");
	   Clase.rif = StringUtils.rightPad(Clase.rif, 18, " ");	   
	   Clase.nombrerif = Clase.nombre + Clase.rif;
	   
	   String itemsString = "["
   		             + "{\"coditem\":\"0013\",\"descitem\":\"Arroz Blanco\",\"aliquota\":\"1200\",\"unimed\":\"UN\",\"tipocantidad\":\"F\",\"cantidad\":\"10,000\",\"valoruni\":\"36,00\",\"inc\":\"00,00\",\"desc\":\"00,00\",\"redondear\":\"false\"},"
   		             + "{\"coditem\":\"0022\",\"descitem\":\"Mantequilla\",\"aliquota\":\"1200\",\"unimed\":\"UN\",\"tipocantidad\":\"F\",\"cantidad\":\"3,000\",\"valoruni\":\"12,00\",\"inc\":\"00,00\",\"desc\":\"00,00\",\"redondear\":\"false\"},"
   		             + "{\"coditem\":\"0035\",\"descitem\":\"Carne\",\"aliquota\":\"1200\",\"unimed\":\"KG\",\"tipocantidad\":\"F\",\"cantidad\":\"10,000\",\"valoruni\":\"7,00\",\"inc\":\"00,00\",\"desc\":\"00,00\",\"redondear\":\"false\"},"
   		             + "]";
	   JSONArray itemsJson = new JSONArray(itemsString);	
	   Clase.itemsArray = itemsJson;
	   
	   Clase.IncrementoDescuento = "D";
	   Clase.TipoIncDesc = "%";
	   Clase.ValorIncremento = "0";
	   Clase.ValorDescuento = "0";	   
	   Clase.FormaPago = "Efectivo";
	   Clase.ValorPago = "3000,00";
	   Clase.NumeroPartesPago = "1";
	   Clase.MsjPago = "Efectivo";
	   Clase.MsjCierre = " Gracias por su compra !";
	   Clase.ActivaGuill = 0;
	  
	   Clase.NumeroCupon();
	   
	   //resp = Clase.EmiteFactura();
	   //if(resp==false){Clase.MostrarMsj("Error de imnpresión de Factura");}	   	   
	}
    
    public boolean ProcesarRetorno(int iRetorno, String metodo){
    	
    	this.MostrarMsj(metodo+": "+Integer.toString(iRetorno));
    	
    	
    	switch(iRetorno){
	   		case 0:
	   			this.MostrarMsj(metodo + ": Error de Comunicación !");
	   			return false;	   			
	   			
	   		case -2:
	   			this.MostrarMsj(metodo + ": Parámetro Inválido !");
	   			return false;
   			
	   		case -3:
	   			this.MostrarMsj(metodo + ": Aliquota no programada !");
	   			return false;
	   			
	   		case -5:
	   			this.MostrarMsj(metodo + ": Error al abrir puerto de comunicaciones !");
	   			return false;	   
	   }
	   
	   if(iRetorno<1){this.MostrarMsj(metodo + ": Error "+metodo+" !"); return false;}
	   
	   return true;
    }
   
    public boolean MsjRetorno(int iRetorno, String metodo){
    	 int Retorno;  
    	 int ack=0, st1=0, st2=0, st3=0;
    	 boolean resp = true;
   	     //Retorno = Bematech.lib.Bematech_FI_RetornoImpressoraMFD(ack,st1,st2,st3);
   	     //Retorno = Bematech.lib.Bematech_FI_RetornoImpressora(ack,st1,st2);   	     
   	     //this.MostrarMsj(Integer.toString(ack)+"-"+Integer.toString(st1)+"-"+Integer.toString(st2)+"-"+Integer.toString(st3));   
    	 return true;
    }
    
    public boolean VerificaEstadoImpresora(){
    	 byte[] ack = new byte[1];
    	 byte[] st1 = new byte[1];
    	 byte[] st2 = new byte[1];
    	     	 
	   	 int Retorno = Bematech.lib.Bematech_FI_VerificaEstadoImpresora(ack,st1,st2);
	   	 	   	 
	   	 String ackstr = new String(ack);
	   	 String st1str = new String(st1);
	   	 String st2str = new String(st2);
	   	 	     	     
	  	 this.MostrarMsj(ack[0]+"-"+st1[0]+"-"+st2[0]);
	  	 
	   	 return true;
   }
    
    
    public void MostrarMsj(String msj){
    	System.out.println(msj);	
    }
   
    public boolean EmiteFactura() throws JSONException, PortInUseException, IOException{
          	
	   boolean resp = true;
	  
	   resp = this.AbreCupom();
	   if(resp==false){return false;}
	   
	   resp = this.ProcesaItems();
	   if(resp==false){return false;}
	  
	   resp = this.SubtotalizaCupom();
	   if(resp==false){return false;}
	   
	   resp = this.IniciaFechamentoCupom();
	   if(resp==false){return false;}
	   
	   resp = this.TotalizaCupom();
	   if(resp==false){return false;}
	   
	   resp = this.EfetuaFormaPagamento();
	   if(resp==false){return false;}
	   
	   resp = this.TerminaFechamentoCupom();
	   if(resp==false){return false;}
	   
	   this.MostrarMsj("Impresión OK !");	   
	   return true;
    }   
    
    public boolean AbreCupom(){
           
       int iRetorno;      
       String metodo = "AbreCupom";
       boolean resp = true;
       
       if(this.nombrerif==""){this.MostrarMsj(metodo + ": Falta el nombre del Cliente !"); return false;}
              
  	   iRetorno = Bematech.lib.Bematech_FI_AbreCupon(this.nombrerif);
  	   resp = this.ProcesarRetorno(iRetorno,metodo);
  	   if(resp==false){return false;}
  	   resp = this.MsjRetorno(iRetorno,metodo);
  	   if(resp==false){return false;}
  	   
	   return true;
	   
    }
   
    public boolean AtivaDesativaGuilhotina(){
        
        int iRetorno;      
        String metodo = "AtivaDesativaGuilhotina";
        boolean resp = true;
        
   	   iRetorno = Bematech.lib.Bematech_FI_AtivaDesativaGuilhotinaMFD(this.ActivaGuill);
   	   resp = this.ProcesarRetorno(iRetorno,metodo);
   	   if(resp==false){return false;}
   	   resp = this.MsjRetorno(iRetorno,metodo);
   	   if(resp==false){return false;}
   	   
 	   return true;
 	   
     }
    
    public boolean ProcesaItems() throws JSONException{
 	   
    	boolean resp = true;   	
    	    	
    	int count = this.itemsArray.length(); 
    	
	    for(int i=0 ; i< count; i++){
	    	JSONObject jsonitem = this.itemsArray.getJSONObject(i);
	    	resp = this.VendeItem(jsonitem);
	 	    if(resp==false){return false;}	    	
    	}
    	 	    
 	    return true;
    }
    
    public boolean VendeItem(JSONObject itemjson) throws JSONException{
	   
       int iRetorno;      
       String metodo = "VendeItem";
       boolean resp = true; 
    	
       String coditem = (String) itemjson.get("coditem");
       String descitem = (String) itemjson.get("descitem");
       String aliquota = (String) itemjson.get("aliquota");
       String unimed = (String) itemjson.get("unimed");
       String cantidad = (String) itemjson.get("cantidad");
       String tipocantidad = (String) itemjson.get("tipocantidad");
       String valoruni = (String) itemjson.get("valoruni");
       String inc = (String) itemjson.get("inc");
       String desc = (String) itemjson.get("desc");
       String redondearStr = (String) itemjson.get("redondear");
       Boolean redondear = Boolean.valueOf(redondearStr);  
       
       this.MostrarMsj(coditem + " " + descitem + " " + cantidad + " " + valoruni);

  	   iRetorno = Bematech.lib.Bematech_FI_VendeItem(coditem,descitem,aliquota,tipocantidad,cantidad,2,valoruni,"%","0000");
       resp = this.ProcesarRetorno(iRetorno,metodo);
  	   if(resp==false){return false;}
	          
	   return true;
    }
   
    public boolean IniciaFechamentoCupom(){
    	
    	int iRetorno;      
        String metodo = "IniciaFechamentoCupom";
        boolean resp = true; 
	    
        iRetorno = Bematech.lib.Bematech_FI_IniciaCierreCupon(this.IncrementoDescuento,this.TipoIncDesc,this.ValorIncremento);
   	    resp = this.ProcesarRetorno(iRetorno,metodo);
   	    if(resp==false){return false;}
    	
	    return true;
    }
    
    public boolean SubtotalizaCupom(){
    	
    	int iRetorno;      
        String metodo = "SubtotalizaCupom";
        boolean resp = true; 
	    
        iRetorno = Bematech.lib.Bematech_FI_SubTotalizaCupomMFD();
   	    resp = this.ProcesarRetorno(iRetorno,metodo);
   	    if(resp==false){return false;}
    	
	    return true;
    }
    
    
    public boolean TotalizaCupom(){
    	
    	int iRetorno;      
        String metodo = "TotalizaCupom";
        boolean resp = true; 
	    
        iRetorno = Bematech.lib.Bematech_FI_TotalizaCupomMFD();
   	    resp = this.ProcesarRetorno(iRetorno,metodo);
   	    if(resp==false){return false;}
    	
	    return true;
    }
    
    
    
    public boolean EfetuaFormaPagamento(){
    	
    	int iRetorno;      
        String metodo = "EfetuaFormaPagamento";
        boolean resp = true; 
           
        
        iRetorno = Bematech.lib.Bematech_FI_EfectuaFormaPago(this.FormaPago,this.ValorPago);
   	    resp = this.ProcesarRetorno(iRetorno,metodo);
   	    if(resp==false){return false;}
   	    
	    return true;
    }
   
    public boolean TerminaFechamentoCupom(){
	   
    	int iRetorno;      
        String metodo = "TerminaFechamentoCupom";
        boolean resp = true; 
	    
        iRetorno = Bematech.lib.Bematech_FI_FinalizarCierreCupon(this.MsjCierre);
        resp = this.ProcesarRetorno(iRetorno,metodo);
   	    if(resp==false){return false;}
        
	    return true;
    }
   
    public String NumeroCupon() throws FileNotFoundException{
 	   
    	 int iRetorno;      
         String metodo = "NumeroCupon";
         String nrocupon ="000001";
        
         boolean resp = true; 
	    
         iRetorno = Bematech.lib.Bematech_FI_NumeroCupon(nrocupon);
         resp = this.ProcesarRetorno(iRetorno,metodo);
     	 if(resp==false){return "false";}       
         //SE TIENE QUE LEER DEL ARCHIVO DE RETORNO YA QUE JAVA NO PUEDE PASAR POR REFERENCIA UN STRING
   	   	 Scanner scan = new Scanner(new File("C:/Retorno.txt"));
	     /*
   	   	  while(scan.hasNextLine()){
	         String line = scan.nextLine();
	          nrocupon = line;
	     }
   	     */
   	     nrocupon = scan.nextLine();
	     this.MostrarMsj(nrocupon);
	     
	     return nrocupon;
    }
    
    
    
    public void RetornoAliquotas(){
 	   int iRetorno;

 	   BemaInteger ACK, ST1, ST2, ST3;
 	   ACK = new BemaInteger();
 	   ST1 = new BemaInteger();
 	   ST2 = new BemaInteger();
 	   ST3 = new BemaInteger();	  
 	   
 	   byte[] resp = new byte[79];
 	   
 	   iRetorno = Bematech.lib.Bematech_FI_RetornoAliquotas(resp);
 	   
 	   String sValor = ""; 
 		for(int i = 0;i < resp.length;i++){
 			sValor = sValor + Character.getNumericValue(resp[i]);
 		}
 		sValor = sValor.replaceAll("-1", ",");
 	   
 		StringTokenizer st = new StringTokenizer(sValor,",");
 		
 		while(st.hasMoreElements()){
 			String sAliquota = (String) st.nextElement();
 			int entero = Integer.parseInt(sAliquota.substring(0,2));
 			int decimal = Integer.parseInt(sAliquota.substring(2,4));			
 			sAliquota = entero+"."+decimal;
 			double Alitxt = Double.parseDouble(sAliquota);
 			System.out.println("Alicuota: "+String.format("%.2f", Alitxt));			
 		}
 	}
    
    public void FormasDePago(){
 	   int iRetorno;

 	   BemaInteger ACK, ST1, ST2, ST3;
 	   ACK = new BemaInteger();
 	   ST1 = new BemaInteger();
 	   ST2 = new BemaInteger();
 	   ST3 = new BemaInteger();	  
 	   
 	   byte[] resp = new byte[3017];
 	   
 	   iRetorno = Bematech.lib.Bematech_FI_VerificaFormasPago(resp);
 	   
 	   String sValor = ""; 
 	   String hexdig = ""; 
 	   int a = 1;
 	   
 	   for(int i = 0;i < resp.length;i++){		    
 		    hexdig = "" + (char)resp[i];
 			sValor = sValor + hexdig.trim();
 			sValor = sValor.trim();
 			if(a==16){if(!sValor.isEmpty()){System.out.println("Tipo de Pago: "+sValor.trim());} sValor=""; a=0; i=i+42;}
 			a++;
 		}
 	   	    
 	}
    
    public void SimboloMoneda(){
 	   int iRetorno;

 	   BemaInteger ACK, ST1, ST2, ST3;
 	   ACK = new BemaInteger();
 	   ST1 = new BemaInteger();
 	   ST2 = new BemaInteger();
 	   ST3 = new BemaInteger();	  
 	   
 	   byte[] resp = new byte[3];
 	   
 	   iRetorno = Bematech.lib.Bematech_FI_SimboloMoneda(resp);
 	   
 	   String sValor = ""; 
 	   String hexdig = ""; 
 	   int a = 1;
 	   
 	   for(int i = 0;i < resp.length;i++){		    
 		    hexdig = "" + (char)resp[i];
 			sValor = sValor + hexdig.trim();
 			sValor = sValor.trim();			
 		}
 	   System.out.println("Moneda: "+sValor);    
 	}
    
    public boolean ModeloImpressora(){
  	   int iRetorno;
  	   boolean resp = true; 
  	   String metodo = "ModeloImpressora";
  	   String modelo="MP4000FI"; 	  
  	   String version="TH FI";
  	 
  	   iRetorno = Bematech.lib.Bematech_FI_ModeloVersionImpresora(modelo,version);
  	   resp = this.ProcesarRetorno(iRetorno,metodo);
 	   if(resp==false){return false;}
 	   resp = this.MsjRetorno(iRetorno,metodo);
 	   if(resp==false){return false;}
  	   System.out.println("modelo: "+modelo);
  	   return true;
  	}
    
}
class BemaInteger {public int number;}
class BemaString {public String buffer;}
   




