/*
* Copyright 2014 - LAit SpA
*				 Realizzato da Icona Management srl su commessa LAit SpA
* Copyright 2015- LAit SpA
*                                                  Aggiornato da LAit SpA
*
* Concesso in licenza a norma dell'EUPL, versione 1.1 o
* successive dell'EUPL (la "Licenza")– non appena saranno
* approvate dalla Commissione europea;
* Non è possibile utilizzare l'opera salvo nel rispetto della Licenza.
* È possibile ottenere una copia della Licenza al seguente indirizzo:
*
* http://ec.europa.eu/idabc/eupl
*
* Salvo diversamente indicato dalla legge applicabile o
* concordato per iscritto, il software distribuito secondo
* i termini della Licenza è distribuito "TAL QUALE",
* SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO,
* esplicite o implicite.
* Si veda la Licenza per la lingua specifica che disciplina
* le autorizzazioni e le limitazioni secondo i termini della
* Licenza.
*/
/**
 * 
 */
package it.laitspa.cpf.spring.sogei;

import it.gov.fatturapa.sdi.fatturapa.v1.CedentePrestatoreType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiAnagraficiCedenteType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiGeneraliDocumentoType;
import it.gov.fatturapa.sdi.fatturapa.v1.DatiGeneraliType;
import it.gov.fatturapa.sdi.fatturapa.v1.FatturaElettronicaBodyType;
import it.gov.fatturapa.sdi.fatturapa.v1.FatturaElettronicaType;
import it.gov.fatturapa.sdi.fatturapa.v1.IdFiscaleType;
import it.laitspa.cpf.model.sogei.fattura.FatturaSogei;
import it.laitspa.cpf.model.sogei.fattura.FatturaSogeiDAO;
import it.laitspa.cpf.model.sogei.inviofilesdi.InvioFileSdiDAO;
import it.laitspa.cpf.model.sogei.inviofilesdi.InvioFileSdiSogei;
import it.laitspa.cpf.model.sogei.statoinvio.StatoInvioSogei;
import it.laitspa.cpf.model.sogei.tipofattura.TipoFatturaSogei;
import it.laitspa.cpf.util.log.LogUtils;
import it.laitspa.cpf.util.misc.DateUtils;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Session;

/**
 * @author andrea
 *
 */
public class SogeiImmissioneLoader
  extends SogeiLoaderImpl
{

  public SogeiImmissioneLoader(Session session, InvioFileSdiSogei flussoSogei,
      List<FatturaElettronicaType> fatture)
  {
    super(session, flussoSogei, fatture);
  }

  /* (non-Javadoc)
   * @see it.laitspa.cpf.spring.sogei.SogeiLoader#loadSogei()
   */
  @Override
  public boolean loadSogei()
  {
    
    InvioFileSdiDAO idao = new InvioFileSdiDAO(session);
    
    // List to store something alreadypresent inside each flux.
    //
    List<Object[]> something_present = new ArrayList<Object[]>();
    Iterator<FatturaElettronicaType> i_fatture = fatture.iterator();
    
    boolean hasError = false;
    StringBuilder e_builder = new StringBuilder();
    
    
    int index = 0;
    while(i_fatture.hasNext())
    {
      LogUtils.info(getClass(), "Processing flux n. " + ++index + " for flux id " + flussoSogei.getCodice());
      FatturaElettronicaType fattura = i_fatture.next();
      
      // Retrieve Cedente
      //
      CedentePrestatoreType cedente = fattura.getFatturaElettronicaHeader().getCedentePrestatore();
      DatiAnagraficiCedenteType anagrafica_cede = cedente.getDatiAnagrafici();
      IdFiscaleType idFiscale = anagrafica_cede.getIdFiscaleIVA();
      
      // Iterate on body children of invoice
      //
      List<FatturaElettronicaBodyType> invoices = fattura.getFatturaElettronicaBody();
      Iterator<FatturaElettronicaBodyType> ir = invoices.iterator();
      FatturaSogeiDAO fdao = new FatturaSogeiDAO(session);
      while(ir.hasNext())
      {
        FatturaElettronicaBodyType body = ir.next();
        DatiGeneraliType datigenerali = body.getDatiGenerali();

        // <DatiGeneraliDocumento>
        //
        DatiGeneraliDocumentoType datidocumento = datigenerali.getDatiGeneraliDocumento();
        String numeroFattura = datidocumento.getNumero();
        Date dataFattura = DateUtils.toDate(datidocumento.getData());

        TipoFatturaSogei tipoFattura =
            (TipoFatturaSogei)fdao.getItemByDescrizione("TipoFatturaSogei", "label", datidocumento
                .getTipoDocumento().value());

        if(tipoFattura == null)
          continue;
        
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(dataFattura);

        Integer anno_fattura = gc.get(Calendar.YEAR); 
        
        boolean is_present = false;
        Iterator<Object[]> i_something_present = something_present.iterator();
        while (i_something_present.hasNext() && !is_present)
        {
          Object[] obj = i_something_present.next();
          String numero = (String) obj[0];
          Integer anno = (Integer) obj[1];
          Integer tipo = (Integer) obj[2];
          
          if (anno.equals(anno_fattura)
              && tipo.equals(tipoFattura.getCodice())
              && numero.equals(numeroFattura))
            is_present = true;
        }

        if (is_present)
        {
          hasError = true;
          e_builder.append(MessageFormat.format("Invoice number {0} is already present in file.", new Object[]{numeroFattura}));
          continue;
        }
        else
        {
          Object[] obj = new Object[]{numeroFattura, anno_fattura, tipoFattura.getCodice()};
          something_present.add(obj);
        }

        // Check for double insertion.
        //
        FatturaSogei already_invoice =
            fdao.retrieveFattura(numeroFattura, dataFattura, tipoFattura.getCodice(),
                idFiscale.getIdPaese(), idFiscale.getIdCodice());
        
        if (already_invoice != null)
        {
          hasError = true;
          e_builder.append(MessageFormat.format("Invoice number {0} is already present in the system.", new Object[]{numeroFattura}));
          continue;
        }
      }
    }
    
    if (hasError)
    {
      LogUtils.error(getClass(), "Validation errors detected for flux id " + flussoSogei.getCodice());
      
      // Send segnalazione error.
      //
      idao.sendSegnalazioneForFlusso(flussoSogei, e_builder.toString());
      
      // Save evento.
      //
      idao.saveEventoFlusso(flussoSogei.getCodice(), "Errori di validazione nel flusso.");
      
      StatoInvioSogei statoNonInviato = (StatoInvioSogei) session.load(StatoInvioSogei.class, StatoInvioSogei.NON_INVIATO);
      flussoSogei.setStatoInvio(statoNonInviato);
      session.update(statoNonInviato);
      return false;
    }
    else
    {
      // Call web services.
      //
      SogeiServiceWrapper sw = new SogeiServiceWrapper(session);
      if (sw.inviaFileSdi(flussoSogei.getCodice()))
      {
        SogeiRicezioneLoader sr = new SogeiRicezioneLoader(session, flussoSogei, fatture);
        sr.loadSogei();
      }
      return true;
    }
  }

}
