#ifndef __CFDIXML_H
	#define __CFDIXML_H

#ifdef __cplusplus

#ifdef _WIN32
	#define DllExport   __declspec( dllexport )
#else
	#define DllExport
#endif

typedef void * hcfdi;
typedef const char *scfdi;
typedef unsigned int cfdires;
typedef void * hconcepto;
typedef void * himpuesto;
typedef void * hnode;
//**************

// dll funcs

extern "C"	{

DllExport
const char *libfacturista_version();

DllExport
hcfdi cfdi_comprobante(scfdi version, scfdi serie, scfdi folio, scfdi fecha,
scfdi formaDePago, scfdi subTotal, scfdi TipoCambio, scfdi Moneda, scfdi total,
scfdi metodoDePago, scfdi tipoDeComprobante, scfdi LugarExpedicion, scfdi NumCtaPago,
scfdi FolioFiscalOrig, scfdi SerieFolioFiscalOrig, scfdi FechaFolioFiscalOrig, scfdi MontoFolioFiscalOrig);

DllExport
hcfdi cfdi_emisor(hcfdi pcfdi, scfdi rfc, scfdi nombre);

DllExport
cfdires cfdi_emisor_regimen(hcfdi pcfdi, scfdi Regimen);

DllExport
cfdires cfdi_emisor_domicilio(hcfdi pcfdi, scfdi calle, scfdi noExterior, scfdi noInterior,
scfdi colonia, scfdi localidad, scfdi municipio, scfdi estado, scfdi pais, scfdi codigoPostal, scfdi referencia);

DllExport
cfdires cfdi_emisor_expedido_en(hcfdi pcfdi, scfdi calle, scfdi noExterior, scfdi noInterior,
scfdi colonia, scfdi localidad, scfdi municipio, scfdi estado, scfdi pais, scfdi codigoPostal, scfdi referencia);

DllExport
hcfdi cfdi_receptor(hcfdi pcfdi, scfdi rfc, scfdi nombre);

DllExport
cfdires cfdi_receptor_domicilio(hcfdi pcfdi, scfdi calle, scfdi noExterior, scfdi noInterior,
scfdi colonia, scfdi localidad, scfdi municipio, scfdi estado, scfdi pais, scfdi codigoPostal, scfdi referencia);

DllExport
himpuesto cfdi_impuestos(hcfdi pcfdi, scfdi totalImpuestosRetenidos, scfdi totalImpuestosTrasladados);

DllExport
cfdires cfdi_impuestos_retencion(hcfdi pcfdi, scfdi impuesto, scfdi importe);

DllExport
cfdires cfdi_impuestos_traslado(hcfdi pcfdi, scfdi impuesto, scfdi importe, scfdi tasa);

DllExport
hconcepto cfdi_concepto(hcfdi pcfdi, scfdi cantidad, scfdi unidad, scfdi noIdentificacion,
scfdi descripcion, scfdi valorUnitario, scfdi importe);

DllExport
cfdires cfdi_concepto_informacionaduanera(hconcepto hc, scfdi numero, scfdi fecha, scfdi aduana);

DllExport
cfdires cfdi_concepto_cuentapredial(hconcepto hc, scfdi numero);

DllExport
cfdires cfdi_concepto_parte(hconcepto hc, scfdi cantidad, scfdi unidad, scfdi noIdentificacion,
scfdi descripcion, scfdi valorUnitario, scfdi importe);

DllExport
cfdires cfdi_concepto_ComplementoConcepto(hconcepto hc);


DllExport
hcfdi cfdi_xml_cargar(hcfdi h, scfdi rutaFuente);

DllExport
int cfdi_xml_guardar(hcfdi h, scfdi rutaDestino, int decorar);

DllExport
int cfdi_xml_validar(hcfdi h, scfdi archivoXML, scfdi archivoXSD, scfdi parametros);

DllExport
int cfdi_sellar_pkcs8(hcfdi h, scfdi rutaLlavePrivada, scfdi contrasena, scfdi rutaCertificado, scfdi rutaDestino, int decorar);

DllExport
int cfdi_sellar_pem(hcfdi h, scfdi rutaLlavePrivada, scfdi contrasena, scfdi rutaCertificado, scfdi rutaDestino, int decorar);

DllExport
int cfdi_sellar(hcfdi h, scfdi rutaLlavePrivada, scfdi rutaCertificado, scfdi rutaDestino, int decorar);

DllExport
int cfdi_timbrar(hcfdi h, scfdi rutaFuente, scfdi rutaDestino, int numeroPAC, scfdi parametros);

DllExport
int cfdi_cancelar(hcfdi h, int numeroPAC, scfdi parametros);

DllExport
int cfdi_recuperar(hcfdi h, scfdi rutaDestino, int numeroPAC, scfdi parametros);

DllExport
const char *cfdi_estado_cuenta(hcfdi h, int numeroPAC, scfdi parametros);

DllExport
const char *cfdi_error(hcfdi h);

DllExport
const char *cfdi_resultado(hcfdi h);


DllExport
const char *cfdi_xml_atributo(hcfdi h, scfdi ruta, scfdi nombre);

DllExport
int cfdi_xml_atributo_agregar(hcfdi h, scfdi ruta, scfdi nombre, scfdi valor);

DllExport
int cfdi_xml_atributo_borrar(hcfdi h, scfdi ruta, scfdi nombre);

// Calcula la cadena original de un CFDI sin complementos, sin usar los archivos XSLT
DllExport
const char *cfdi_cadena_original_basica(hcfdi h);

// Indica si las funciones de sellado usaran la cadena original basica (usar==1)
// o la calculada con archivos XSLT (usar==0)
DllExport
void cfdi_usar_cadena_original_basica(hcfdi h, int usar);

// Calcula la cadena original de un CFDI con o sin complementos, usando los archivso XSLT
DllExport
const char *cfdi_cadena_original(hcfdi h);

DllExport
const char *cfdi_cadena_original_sat(hcfdi h);

DllExport
const char *cfdi_uuid(hcfdi h);

DllExport
const char *cfdi_fecha_timbrado(hcfdi h);

DllExport
const char *cfdi_numero_certificado_sat(hcfdi h);

DllExport
const char *cfdi_sello_cfd(hcfdi h);

DllExport
const char *cfdi_sello_sat(hcfdi h);

DllExport
const char *cfdi_sello(hcfdi h);

DllExport
const char *cfdi_fecha(hcfdi h);

// si no damos rutaCertificado, lo toma del XML
DllExport
const char *cfdi_numero_certificado(hcfdi h, scfdi rutaCertificado);


// Call with root node and "acp" for windows programs not handling utf8
DllExport
int xml_caller_charset(hnode h, scfdi charset);

// Return the node handler for the path specified, if h==0 it will return the root node
DllExport
hnode xml_node(hnode h, scfdi path);

// Return the number of children nodes
DllExport
int xml_node_children_number(hnode h);

// Return a node handler for the index-th child, it is 1-based
DllExport
hnode xml_node_by_index(hnode h, int index);

// Return the node name
DllExport
const char *xml_node_name(hnode h);

// Return a node handler for the child with the asked name
DllExport
hnode xml_node_by_name(hnode h, scfdi name);

// Return the value of the asked attribute, empty if it does not exist
DllExport
const char *xml_node_attribute(hnode h, scfdi name);


}
#endif



#endif
// timbrado.cpp
// Ejemplo de uso de libfacturista.dll en C++ (cpp)
//* Ariel Medina - 2013 - facturista.com

// g++ -lfacturista timbrado.cpp -o timbrado.bin

#include <iostream>
#include <string>
#include <cstring>
#include "libfacturista.h"

const char *gcnombrePrograma="facturista.com::timbrado";

bool timbrar(const char *xml, const char *xmltim, bool pruebas, bool solotimbrado);


// ./timbrado.bin archivoFuente.xml archivoDestino.xml
int main(int argc, char **argv)
{
if(argc<3)
	{
	std::cerr<<"Use: "<<argv[0]<<" archivoFuente.xml archivoDestino.xml\n";
	return -1;
	}


if(timbrar(argv[1],argv[2],true,true))
	return 0;

return -2;
}

// 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
bool timbrar(const char *xml, const char *xmltim, bool pruebas, bool solotimbrado)
{
	void *h;
	std::string timbre, params, rfc, uuid;

	// Los nombres de archivo no deberian estar vacios
	if(strlen(xml)<1 || strlen(xmltim)<1)
		{
		std::cerr<<"Nombre de archivo fuente o destino no es valido";
		return false;
		}


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

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


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

	return false;

}