// Program.cs
// Ejemplo en C# (c sharp) para usar libfacturista
// una biblioteca (dll o libreria) para generar, sellar y timbrar CFDI 3.2 (XML)
// Ariel Medina - 2013 - facturista.com

using System;
using lfApi=libfacturista.utf16Api; // libfacturista_cs.dll
//using lfApi=libfacturista.ansiApi; // libfacturista_cs.dll
using System.Runtime.InteropServices;

namespace libfacturista_cs
{
    class Program
    {

		string gcnombrePrograma="facturista.com::libfacturista";
		
		// Funcion para realizar el timbrado, parametros:
		// xml - archivoFuente
		// xmltim - archivoDestino
		// pruebas - true si queremos servidor de pruebas
		// solotimbrado - true si queremos servicio de Solo Timbrado
		// h - manejador del XML, si es diferente de 0, lo consideramos como el XML fuente e ignoramos el primer parametro
		static bool timbrar(string xml, string xmltim, bool pruebas, bool solotimbrado, int h)
		{
			string timbre, paramsPAC, rfc, uuid;

			// Los nombres de archivo no deberian estar vacios
			if((h==0 && xml.Length<1) || xmltim.Length<1)
				{
				Console.WriteLine("Nombre de archivo fuente o destino no es valido");
				return false;
				}

			if(h==0)
				{
				// Solo se carga si la estructura XML es correcta
				h=lfApi.cfdi_xml_cargar(0,xml);
				}
				
			if(h!=0)
				{
				// Aprovechamos para verificar si tiene timbre
                timbre = lfApi.cfdi_xml_atributo(h, "cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital", "UUID");
				if(timbre.Length>0)
					{
					Console.WriteLine("El archivo ya tiene timbre: "+timbre);
					return false;
					}

				// Obtenemos el RFC del emisor
                rfc = lfApi.cfdi_xml_atributo(h, "cfdi:Comprobante/cfdi:Emisor", "rfc");
				if(rfc.Length==0)
					{
					Console.WriteLine("No se pudo determinar el RFC");
					return false;
					}
		
				// Parametro TransaccionID para el PAC
				paramsPAC="TransaccionID=1234567890";
		
				// Si se trata de pruebas, ponemos el servidor y puerto adecuado en los parametros
				if(pruebas)
					paramsPAC=paramsPAC+";RFC=AAA010101AAA;Servidor=pruebas.ecodex.com.mx;Puerto=2044";
				else
					paramsPAC=paramsPAC+";RFC="+rfc;


				// Si no quiere solo timbrado, entonces indicamos al PAC que (re)selle
				if(!solotimbrado)
					paramsPAC=paramsPAC+";Sellar=1";
		
				// Intentamos timbrar
                if (lfApi.cfdi_timbrar(h, xml, xmltim, 1, paramsPAC) > 0)
					{
                    h = lfApi.cfdi_xml_cargar(h, xmltim);
					if (h!=0)
						{
                        uuid = lfApi.cfdi_xml_atributo(h, "cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital", "UUID");
						Console.WriteLine("Folio fiscal : "+uuid+"; archivo: "+xmltim);
						return true;
						}
					else
						Console.WriteLine("La factura fue timbrada pero no se pudo cargar; archivo "+xmltim);
					}
				else
                    Console.WriteLine("Ha fallado el timbrado, " + lfApi.cfdi_error(h));
				}
            else
                Console.WriteLine(lfApi.cfdi_error(0));

			return false;

		}


		
        static int Main(string[] args)
            {
            lfApi.init();
            
            // Descomente la siguiente seccion si desea timbrar el archivo de ejemplo
			/*
            if (timbrar("cfdi_ejemplo.xml", "cfdi_timbrado_csharp.xml", true, false))
                {
                int h = 0;
                string estadoCuenta = lfApi.cfdi_estado_cuenta(h, 1, "RFC=AAA010101AAA;TransaccionID=456;Servidor=pruebas.ecodex.com.mx;Puerto=2044");
                Console.WriteLine(estadoCuenta);

	            string version = lfApi.libfacturista_version();
	            Console.WriteLine(version);
                return 0;
                }
            else
                return -2;
            */

			int h, he, hr, hc, hi;
			string rutaLlavePrivada, contrasena, rutaCertificado, rutaDestino, xmlTimbrado, version, estadoCuenta;
	
			rutaLlavePrivada="./aaa010101aaa__csd_01.key";
			contrasena="12345678a";
			rutaCertificado="./aaa010101aaa__csd_01.cer";
			rutaDestino="./cfdi_sellado.xml";
			xmlTimbrado="./cfdi_timbrado_csharp.xml";

			h=lfApi.cfdi_comprobante("3.2", "A", "1234", "2013-06-27T18:43:11", "Pago en una sola exhibicion", "6172.50", "12.34", "USD", "7124.75", "Efectivo", "ingreso", "Campeche, Campeche", "3849", "", "", "", "");
			  

			he=lfApi.cfdi_emisor(h,"AAA010101AAA","facturista.com");
			if (he==0)
				{
				Console.WriteLine( lfApi.cfdi_error(h)  );
				return -1;
				}

			lfApi.cfdi_emisor_domicilio(he,"31", "7", "Piso 3A", "Col. Mexico", "Campeche", "Municipio de Campeche", "Campeche", "Mexico", "24000", "Por la CFE");
	
			// En caso de ser una sucursal, agregamos su direccion
			lfApi.cfdi_emisor_expedido_en(he,"39", "8", "Depto. 25", "Col. Jalisco", "San Nicolas de los Garza", "Monterrey", "Nuevo Leon", "Mexico", "74000", "Cerca de Telmex");


			lfApi.cfdi_emisor_regimen(he,"Regimen 1");
			lfApi.cfdi_emisor_regimen(he,"Regimen 2");

			// el RFC de los clientes no debe contener guiones o espacios
			hr=lfApi.cfdi_receptor(h,"X&XX010101AAA","nombre_tu_cliente");
			// los clientes deben tener desglosada su direccion para poder llenar los campos del receptor
			lfApi.cfdi_receptor_domicilio(hr,"Paseo de Montejo", "1234", "456", "Col. Europea", "Ciudad gotica", "Municipio de Merida", "Yucatan", "Mexico", "38294", "Por la cascada");


			// aqui ponemos el detalle de la factura, en vez de los conceptos del ejemplo
			// deberia poner información de su BD
			hc=lfApi.cfdi_concepto(h,"10", "PZA", "1", "Memoria USB", "123.45", "1234.50");
			lfApi.cfdi_concepto_informacionaduanera(hc,"12345", "2011-01-01","Aduana nogales");
			 
			hc=lfApi.cfdi_concepto(h,"10", "PZA", "2", "Memoria USB", "123.45", "1234.50");
			lfApi.cfdi_concepto_cuentapredial(hc,"3836463729385495");
			 
			hc=lfApi.cfdi_concepto(h,"10", "PZA", "3", "Memoria USB", "123.45", "1234.50");
			lfApi.cfdi_concepto_parte(h,"10", "PZA", "3", "Parte 1", "123.45", "1234.50");
			lfApi.cfdi_concepto_parte(h,"10", "PZA", "3", "Parte 2", "123.45", "1234.50");
			 
			hc=lfApi.cfdi_concepto(h,"10", "PZA", "4", "Memoria USB", "123.45", "1234.50");
			 
			hc=lfApi.cfdi_concepto(h,"10", "PZA", "5", "Memoria USB", "123.45", "1234.50");
			
			// Probamos el complemento iedu (Instituciones Educativas)
			hc=lfApi.cfdi_concepto(h,"1", "NA", "6", "Pago de educacion, mes de septiembre", "123.45", "1234.50");
			lfApi.cfdi_iedu( h, "1.0" , "Nombre Del Alumno" , "XIZW840214HYFHJW15", "Bachillerato o su equivalente", "04DPRO452V", "AAA010101AAA" , "");


			hi=lfApi.cfdi_impuestos(h,"35.35","987.60");
			  
			lfApi.cfdi_impuestos_retencion(hi,"ISR","12.12");
			lfApi.cfdi_impuestos_retencion(hi,"IVA","23.23");
			  
			lfApi.cfdi_impuestos_traslado(hi,"IVA", "987.60", "16.00");
			lfApi.cfdi_impuestos_traslado(hi,"IEPS", "0.00", "0.00");


			Console.WriteLine("Cadena original:" + lfApi.cfdi_cadena_original(h)  );
	
			// Si es DLL demo, no se guarda en un archivo el XML sellado, pero se queda en memoria
			// para poder timbrarlo; al final obtenemos el XML timbrado en un archivo
			if ( lfApi.cfdi_sellar_pkcs8(h, rutaLlavePrivada, contrasena, rutaCertificado, rutaDestino,1) != 0 )
				{
				// Se ha comentado la siguiente llamada a funcion, que es más elaborada, pero puede confundir al principio
				//if(timbrar("cfdi_ejemplo.xml",xmlTimbrado,true,false,0))
				//if(timbrar("",xmlTimbrado,true,false,h))
				
				// Parametros para el PAC 1 (Ecodex)
				string paramsPAC = "TransaccionID=1234567890;RFC=AAA010101AAA;Servidor=pruebas.ecodex.com.mx;Puerto=2044;Sellar=1";
				// poniendo la cadena vacia en el segundo parametro, se timbra lo que hay en memoria
				if (lfApi.cfdi_timbrar(h, "", xmlTimbrado, 1, paramsPAC) > 0)
					{
				    estadoCuenta = lfApi.cfdi_estado_cuenta(h, 1, "RFC=AAA010101AAA;TransaccionID=456;Servidor=pruebas.ecodex.com.mx;Puerto=2044");
					Console.WriteLine(estadoCuenta);
					}
				else
					Console.WriteLine("Error al timbrar: " + lfApi.cfdi_error(h) );
				}
			else
					Console.WriteLine("Error al sellar: " + lfApi.cfdi_error(h) );
		

			version = lfApi.libfacturista_version();
			Console.WriteLine(version);

			return 0;
            }
    }
}