#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
This program get params to send data to webservice
Need:
 -f file nam to define the file with config params and data
 -e file name used for error
 -m send_mode Manual/Json if not provided send_mode=Json (Manual need XML element into JSON, Json need Body Element whit data serialized)")

When program is called with Json mode, into the param file the element "Body" is needed at the same level as "Parametri".
Body element contain data to send to webservice stored as Json format.

When program is called with Manual mode, into the param file the element "XMLBODYFileName" element is needed into "Parametri" section.
"XMLBODYFileName" element contain file name with data to send to webservice stored as XML format, this data is sent as it is to the web service as Body data of the XML document.

Information for secuirty are taken from "Header" section of the param file and added to the XML sent to the web service.

This program prompt to the standard output information about error or debug purpouse.

When program found an error that is able to manage the message is writed into the file specified into args.
At the end of the execution the response of the webservice is writed into the file specified into Parametri section of param file

Prams are:
-f / --file_name             dest="file_name"             type="string"     set file name to process [REQUIRED]
-e / --error_file_name       dest="error_file_name"       type="string"     set file name to process [REQUIRED]"
-m / --send_mode             dest="send_mode"             type="string"     set send mode: Manual/Json
"""

import soap_mipaaf
import re, sys, os, datetime, time
import json
import yaml
from pysimplesoap.simplexml import SimpleXMLElement
import xml.etree.ElementTree as ET

if not hasattr(datetime.datetime,'strptime'):  #added for Python < 2.5
    def strptime(date_string,format):
        return datetime.datetime(*(time.strptime(date_string, format)[0:6]))
else:
    strptime = datetime.datetime.strptime

def logmsg(msg,options):
    if ( options.verbose ):
        print msg
    
if __name__ == "__main__":
    from optparse import OptionParser
    usage = "usage: %prog [options] argument"
    parser = OptionParser(usage=usage)
    parser.set_defaults(mode="query")
    parser.add_option("-f", "--file_name", dest="file_name", action="store", type="string",
                      help="set file name to process [REQUIRED]")
    parser.add_option("-e", "--error_file_name", dest="error_file_name", action="store", type="string",
                      help="set file name to process [REQUIRED]")
    parser.add_option("-m", "--send_mode", dest="send_mode", action="store", type="string",
                      help="set send mode Manual/Json if not provided send_mode=Json (Manual need XML element into JSON, Json need Body Element whit data serialized)")
    parser.add_option("-t", "--type", dest="type", action="store", type="string", 
                      help="set type of element to delete ('oper,vasi,vigne')")
    parser.add_option("-v", "--verbose", dest="verbose", action="count", default=0,
                      help="debug conversation")
    parser.add_option("-n", "--nosend", dest="nosend", action="store", type="string",
                      help="set send nosend True/False if you want call webservice or reuse a previous reply")
    (options, args) = parser.parse_args()
    if not options.file_name or not options.error_file_name:
        parser.error("-f file_name  is required; try -h")
    if not options.file_name or not options.error_file_name:
        parser.error("-e error_file_name  is required; try -h")
    if not options.send_mode:
        options.send_mode = "Json"
    #         parser.error("-m send_mode  is required; try -h")
    def errlog(msg):
        print >>sys.stderr,"%s - %s" % (datetime.datetime.now().ctime(), msg)
    logmsg("options: "+ str(options)+ " || args: "+ str(args),options)
    for arg in args:
        logmsg("arg: " + arg,options)
    file_error = options.error_file_name
    file_errorGetAll = "getall"+file_error
    output = ""
    
    callstring = '../soapenv/bin/python soap_mipaaf.py -f '+options.file_name+" -m "+options.send_mode+" -e "+options.error_file_name
    if options.verbose:
        callstring+= ' -v 1'
    response = 0
    if ( not options.nosend or options.nosend != "True"):
        try:
        	response = os.system(callstring)
        except Exception as e:
            logmsg(e,options)
        if ( response == 0 ):
            logmsg("Done",options)
        else:
            logmsg("Fail",options)

    if ( response == 0 ):
        datastring = ""
        datajson = ""
        dict_error = {}
        XML = ""
        #EsitoFileName
        datajson={}
        try:
            with open(options.file_name) as data_file:
                try:
                    datastring = data_file.read()
                    datajson = yaml.safe_load(datastring)
                except Exception as e:
                    errlog("ERRORE: File json di input mal formato. Errore nella conversione dei dati del file ison di input in json.")
                    logmsg(e,options)
                    errlog(e)
                    dict_error = {"error message":str(e)}
                    #Scrittura su file dei dati ritornati dalla chiamata del metodo richiesto sul webservice
                    with open(file_error, 'w') as f:
                        json.dump(dict_error, f)
                    sys.exit(5)
        except Exception as e:
            errlog("ERRORE: Apertura file non riuscita")
            logmsg(e,options)
            errlog(e)
            
            #Scrittura su file dei dati ritornati dalla chiamata del metodo richiesto sul webservice
            with open(file_error, 'w') as f:
                json.dump(dict_error, f)
            sys.exit(5)
        logmsg(datajson,options)
        
        try:
            #Parametri da av2000
            parametri_av2000 = datajson['Parametri']
            wsdl=parametri_av2000['wsdl']
            esitoFileName=parametri_av2000['EsitoFileName']
        except Exception as e:
            errlog("ERRORE: ERRORE nella lettura del file json")
            logmsg(e,options)
            errlog(e)
            dict_error = {"error message":str(e)}
            #Scrittura su file dei dati ritornati dalla chiamata del metodo richiesto sul webservice
            with open(file_errorGetAll, 'w') as f:
                json.dump(dict_error, f)
            sys.exit(1)

        try:
            with open(esitoFileName) as data_file:
                try:
                    XML = data_file.read()
                except Exception as e:
                    errlog("ERRORE: XMLBODYFileName di input mal formato. Errore nella lettura di: "+esitoFileName)
                    logmsg(e,options)
                    errlog(e)
                    dict_error = {"error message":str(e)}
                    #Scrittura su file dei dati ritornati dalla chiamata del metodo richiesto sul webservice
                    with open(file_errorGetAll, 'w') as f:
                        json.dump(dict_error, f)
                    sys.exit(5)
        except Exception as e:
            errlog("ERRORE: Apertura file "+XMLBODYFileName+" non riuscita")
            logmsg(e,options)
            errlog(e)
            dict_error = {"error message":str(e)}
            #Scrittura su file dei dati ritornati dalla chiamata del metodo richiesto sul webservice
            with open(file_errorGetAll, 'w') as f:
                json.dump(dict_error, f)
            sys.exit(5)
        
        bPersonaGiuridica = False
        XMLBODYFileName = parametri_av2000['XMLBODYFileName']
        treeBody = ET.parse(XMLBODYFileName)
        rootbody = treeBody.getroot()
        codOper_type = rootbody[0][0].tag.split("}")[1].strip()
        codOper_value = rootbody[0][0].text.strip()
        if ( codOper_type == "PersonaGiuridica" ):
            bPersonaGiuridica = True
        codiceIcqrf = ''
        if ( len(rootbody) >= 2 ):
            codiceIcqrf = rootbody[1].text.strip()
#         dataOperIni = ''
#         if ( options.type == "oper" ):
#             dataOperIni = rootbody[2].text.strip()
#         dataOperFine = ""
#         if ( len(rootbody) >= 4 ):
#             codtype = rootbody[3].split("}")[1]
#             if ( codtype == "DataOperFine" ):
#                 dataOperFine = rootbody[3].text
#             else:
#                 msgError = "ERRORE: DataOperFine. Rilevato: "+codtype+" valore:"+rootbody[3].text
#                 errlog(msgError)
#                 logmsg(msgError,options)
#                 sys.exit(6)
        
        logmsg("XMLBODYFileName: "+XMLBODYFileName,options) 
        logmsg("codOper_type: "+codOper_type,options)
        logmsg("codOper_value: "+codOper_value,options)
        logmsg("codiceIcqrf: "+codiceIcqrf,options)
#         logmsg("dataOperIni: "+dataOperIni,options)
#         logmsg("dataOperFine: "+dataOperFine,options)
        logmsg("esitoFileName: "+esitoFileName,options)
        tree = ET.parse(esitoFileName)
        root = tree.getroot()
        logmsg("root[0][0] operation: "+str(root[0][0]),options)
        logmsg("root[0][0] length: "+str(len(root[0][0])),options)
        operOutput = root[0][0]
        header = datajson['Header']
        username = header['username'].strip()
        password = header['password'].strip()
        nomeServizio = ""
        operazioni = []
        dataObjectOutput = {"username":username,"password":password,"nomeServizio":nomeServizio,"bPersonaGiuridica":bPersonaGiuridica,"CodOper":codOper_value,"CodiceIcqrf":codiceIcqrf,"operazioni":operazioni}
        for elemOperOutput in operOutput:
            if ( options.type == "oper" ):
                operazione = elemOperOutput
                elemDescri = operazione.tag.split("}")[1].strip()
                if ( elemDescri != "Esito"):
                    if ( len(elemOperOutput) > 0 and len(elemOperOutput[0]) > 0 ):
                        logmsg("elemOperOutput DettaglioOperazione: "+str(elemOperOutput),options)
                        logmsg("elemOperOutput length: "+str(len(elemOperOutput)),options)
                        logmsg("elemOperOutput[0] Operazione: "+str(elemOperOutput[0]),options)
                        logmsg("elemOperOutput[0] length: "+str(len(elemOperOutput[0])),options)
                        logmsg("DettaglioOperazione: "+str(elemOperOutput),options)
                        operazione = elemOperOutput[0]
                        logmsg("Operazione: "+str(operazione),options)
                        logmsg("Operazione.tag name: "+str(operazione.tag),options)
                        codOperazione = operazione.tag.split("}")[1].strip()
                        logmsg("Operazione cod: "+str(codOperazione),options)
                        dataOperazione = operazione[1].text.strip()
                        logmsg("dataOperazione: "+str(dataOperazione),options)
                        numOperazione = operazione[0].text.strip()
                        logmsg("numOperazione: "+str(numOperazione),options)
                        operazioni.append({"DataOperazione":dataOperazione,"NumOperazione":numOperazione,"CodOperazione":codOperazione})
            elif ( options.type == "vasi" ):
                operazione = elemOperOutput
                elemDescri = operazione.tag.split("}")[1].strip()
                if ( elemDescri != "codOper" and elemDescri != "Esito"):
                    codVaso = elemOperOutput[0].text
                    tipoVaso = elemOperOutput[1].text
                    descrizione = elemOperOutput[2].text
                    volume = elemOperOutput[3].text
                    operazioni.append({"CodVaso":codVaso,"TipoVaso":tipoVaso,"Descrizione":descrizione,"Volume":volume})
            elif ( options.type == "vigne" ):
                operazione = elemOperOutput
                elemDescri = operazione.tag.split("}")[1].strip()
                if ( elemDescri != "codOper" and elemDescri != "Esito" ):
                    codVigna = elemOperOutput[0].text
                    descrizione = elemOperOutput[1].text
                    operazioni.append({"CodVigna":codVigna,"Descrizione":descrizione})
            elif ( options.type == "sogg" ):
                operazione = elemOperOutput
                elemDescri = operazione.tag.split("}")[1].strip()
                if ( elemDescri != "codOper" and elemDescri != "Esito"):
                    logmsg("CodiceSoggetto: "+str(elemOperOutput[0]),options)
                    codiceSoggetto = elemOperOutput[0].text
                    #CUAA = elemOperOutput[1].text
                    #TipoSoggetto = elemOperOutput[2].text
                    #Nome = elemOperOutput[3].text
                    #Cognome = elemOperOutput[4].text
                    #RagioneSociale = elemOperOutput[5].text
                    #IndirizzoSede = elemOperOutput[6].text
                    operazioni.append({"CodiceSoggetto":codiceSoggetto})
            else:
                e = "ERRORE: Tipologia operazione non gestita: "+options.type
                errlog(e)
                logmsg(e,options)
                dict_error = {"error message":str(e)}
                #Scrittura su file dei dati ritornati dalla chiamata del metodo richiesto sul webservice
                with open(file_errorGetAll, 'w') as f:
                    json.dump(dict_error, f)
                sys.exit(10)
        
        logmsg("operazioni: "+str(operazioni),options)
        dataObjectOutput["operazioni"]=operazioni
        logmsg("dataObjectOutput: "+str(dataObjectOutput),options)
        if ( len(operazioni) == 0 ):
            logmsg("No operazioni found!",options)
        else:
#           --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            cancObjectInput = ''
            cancNomeServizio = ''
            eliminaCompleteTemplate = ''
            codOperTemplate = ''
            if ( options.type == "oper" ):
                cancNomeServizio = 'CancOperSiRPV'
                cancObjectInput = cancNomeServizio+'Input'
                eliminaTemplate = '<OperElimina><DataOperazione>%s</DataOperazione><NumOperazione>%s</NumOperazione><CodOperazione>%s</CodOperazione></OperElimina>'
                for operazione in operazioni:
                    eliminaCompleteTemplate += eliminaTemplate % (operazione['DataOperazione'],operazione['NumOperazione'],operazione['CodOperazione'])
            elif ( options.type == "vasi" ):
                cancNomeServizio = 'CancVasiSiRPV'
                cancObjectInput = cancNomeServizio+'Input'
                eliminaTemplate = '<VasoElimina><CodVaso>%s</CodVaso></VasoElimina>'
                for operazione in operazioni:
                    eliminaCompleteTemplate += eliminaTemplate % (operazione['CodVaso'])
            elif ( options.type == "vigne" ):
                cancNomeServizio = 'CancVigneSiRPV'
                cancObjectInput = cancNomeServizio+'Input'
                eliminaTemplate = '<VignaElimina><CodVigna>%s</CodVigna></VignaElimina>'
                for operazione in operazioni:
                    eliminaCompleteTemplate += eliminaTemplate % (operazione['CodVigna'])
            elif ( options.type == "sogg" ):
                cancNomeServizio = 'CancSoggSiRPV'
                cancObjectInput = cancNomeServizio+'Input'
                eliminaTemplate = '<SoggettoElimina><CodiceSoggetto>%s</CodiceSoggetto></SoggettoElimina>'
                for operazione in operazioni:
                    eliminaCompleteTemplate += eliminaTemplate % (operazione['CodiceSoggetto'])
            else:
                e = "ERRORE: Tipologia eliminazione non riconosciuta: "+options.type
                errlog(e)
                logmsg(e,options)
                dict_error = {"error message":str(e)}
                #Scrittura su file dei dati ritornati dalla chiamata del metodo richiesto sul webservice
                with open(file_errorGetAll, 'w') as f:
                    json.dump(dict_error, f)
                sys.exit(9)
            dataObjectOutput['nomeServizio'] = cancNomeServizio
            strMessage = ''
            openMessage = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://cooperazione.sian.it/schema/SoapAutenticazione">'
            #openMessage = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
            strMessage += openMessage
            openHeader = '<soap:Header>'
            strMessage += openHeader
            headerTemplate = '<soap:SOAPAutenticazione><username>%s</username><password>%s</password><nomeServizio>%s</nomeServizio></soap:SOAPAutenticazione>'
            strMessage += headerTemplate % (dataObjectOutput['username'],dataObjectOutput['password'],dataObjectOutput['nomeServizio'])
            closeHeader = '</soap:Header>'
            strMessage += closeHeader
            openBody = '<soap:Body>'
            strMessage += openBody
            
            if bPersonaGiuridica:
                codOperTemplate = '<PersonaGiuridica>%s</PersonaGiuridica>' % (codOper_value)
            else:
                codOperTemplate = '<PersonaFisica>%s</PersonaFisica>' % (codOper_value)
            
#             wsdlurlsplit = wsdl.split('/')
#             wsdlurl = wsdlurlsplit[2]
#             wsdlurl = "http://"+wsdlurl+"/schema/wsmrga/" #Precedentemente era impostato a wsmrgc probabilmente per il registro degli zuccheri
            wsdlurl = "http://cooperazione.sian.it/schema/wsmrga/"
            bodyTemplate = '<'+cancObjectInput+' xmlns="'+wsdlurl+'"><CodOper>%s</CodOper>'
            if ( options.type != "sogg" ):
                bodyTemplate += '<CodiceIcqrf>%s</CodiceIcqrf>'
            bodyTemplate += '%s</'+cancObjectInput+'>'
            file_callCancOperSiRPVBody = ''
            if ( options.type == "sogg" ):
                file_callCancOperSiRPVBody = bodyTemplate % (codOperTemplate,eliminaCompleteTemplate)
            else:
                file_callCancOperSiRPVBody = bodyTemplate % (codOperTemplate,codiceIcqrf,eliminaCompleteTemplate)
            strMessage += file_callCancOperSiRPVBody
#           --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            closeBody = '</soap:Body>'
            strMessage += closeBody
            closeMessage = '</soap:Envelope>'
            strMessage += closeMessage
            filepath = ""
            if ( options.file_name.find("/") >= 0 ):
                filepathSplit = options.file_name.split("/")
                filepathSplitLen = len(filepathSplit)
                indexFilepathSplitLen = 0
                for data in filepathSplit:
                    indexFilepathSplitLen+= 1
                    if ( indexFilepathSplitLen != filepathSplitLen):
                        filepath += data + "/"
            file_callCancOperSiRPV = filepath + cancNomeServizio +'Full.xml'
            file_callCancOperSiRPVBodyName = filepath + cancNomeServizio + 'Body.xml'
            file_callCancOperSiRPVJson = filepath + cancNomeServizio + 'Json.json'
            file_callCancOperSiRPVError = filepath + cancNomeServizio + 'Error.txt'
            file_callCancOperSiRPVErrorEsito = filepath + cancNomeServizio + "Esito.xml"
            file_callCancMovSyncJson = filepath + cancNomeServizio + "_sync.json"
            dict_conf = {
                "Parametri":{
                    "authHeader":parametri_av2000["authHeader"],
                    "wsdl":parametri_av2000["wsdl"].split("?")[0]+"Async?"+parametri_av2000["wsdl"].split("?")[1],
                    "EsitoFileName":file_callCancOperSiRPVErrorEsito,
                    "XMLBODYFileName":file_callCancOperSiRPVBodyName
                }
                ,"Header":{
                    "nomeServizio":cancNomeServizio,
                    "username":dataObjectOutput['username'],
                    "password":dataObjectOutput['password']
                }
            }
            with open(file_callCancOperSiRPVJson, 'w') as f:
                json.dump(dict_conf, f)
            with open(file_callCancOperSiRPVBodyName, 'w') as f:
                f.write(file_callCancOperSiRPVBody)
            callstring = '../soapenv/bin/python soap_mipaaf.py -f ' + file_callCancOperSiRPVJson + " -m XML -e " + file_callCancOperSiRPVError
            if options.verbose:
                callstring+= ' -v 1'
            logmsg(callstring,options)
            try:
                response = os.system(callstring)
            except Exception as e:
                logmsg(e,options)
            if ( response == 0 ):
                logmsg("Done Canc",options)
                try:
                    treeOutput = ET.parse(file_callCancOperSiRPVErrorEsito)
                    rootOutput = treeOutput.getroot()
                    IdTrasmissione = rootOutput[0][0][1].text.strip()
                    dict_conf_done_check = {
                        "Parametri":{
                            "authHeader":"SOAPAutenticazione"
                            ,"wsdl":wsdl
                            ,"EsitoFileName":filepath + cancNomeServizio + "_sync_esito.xml"
                        }
                        ,"Header":{
                            "nomeServizio":"Get"+cancNomeServizio
                            ,"username":dataObjectOutput['username']
                            ,"password":dataObjectOutput['password']
                        }
                        ,"Body":{
                                 "IdTrasmissione":IdTrasmissione
                        }
                    }
                    try:
                        with open(file_callCancMovSyncJson, 'w') as f:
                            json.dump(dict_conf_done_check, f)
                    except Exception as e:
                        errlog("ERRORE: Scrittura file "+file_callCancMovSyncJson+" non riuscita")
                        logmsg(e,options)
                        errlog(e)
                        dict_error = {"error message":str(e)}
                        #Scrittura su file dei dati ritornati dalla chiamata del metodo richiesto sul webservice
                        with open(file_errorGetAll, 'w') as f:
                            json.dump(dict_error, f)
                        sys.exit(8)
                except Exception as e:
                    errlog("ERRORE: Apertura file "+file_callCancOperSiRPVErrorEsito+" non riuscita")
                    logmsg(e,options)
                    errlog(e)
                    dict_error = {"error message":str(e)}
                    #Scrittura su file dei dati ritornati dalla chiamata del metodo richiesto sul webservice
                    with open(file_errorGetAll, 'w') as f:
                        json.dump(dict_error, f)
                    sys.exit(7)
            else:
                logmsg("Fail Canc",options)