/*
* 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.model.sogei.inviofilesdi;

import it.laitspa.cpf.model.DAO;
import it.laitspa.cpf.model.sogei.evento.EventoSogei;
import it.laitspa.cpf.model.sogei.soggetto.SoggettoSogei;
import it.laitspa.cpf.model.sogei.statoinvio.StatoInvioSogei;
import it.laitspa.cpf.model.sogei.trasmissione.TrasmissioneSogei;
import it.laitspa.cpf.util.exceptions.FacadeException;
import it.laitspa.cpf.util.log.LogUtils;
import it.laitspa.cpf.util.mail.MailUtils;
import it.laitspa.cpf.util.misc.JndiServiceLocator;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.mail.Message;

import org.hibernate.Query;
import org.hibernate.Session;

/**
 * @author andrea
 *
 */
public class InvioFileSdiDAO
  extends DAO
{

  public InvioFileSdiDAO(Session session)
  {
    super(session);
  }

  
  public InvioFileSdiSogei getNextToBeLoaded()
  {
    String hql = "select invio from InvioFileSdiSogei invio "
        + "where invio.dataElaborazione is null and "
        + "invio.statoInvio.codice in (:statoRicevuto, :statoImmesso) "
        + "order by invio.dataRicezione";
    
    Query q = session.createQuery(hql);
    q.setParameter("statoRicevuto", StatoInvioSogei.RICEVUTO);
    q.setParameter("statoImmesso", StatoInvioSogei.IMMESSO);
    q.setMaxResults(1);
    
    InvioFileSdiSogei invio = (InvioFileSdiSogei)q.uniqueResult();
    if (invio != null)
    {
      invio.setDataElaborazione(new Date());
      session.update(invio);
    }
    logger.info("getNextToBeLoaded returned InvioFileSdiSogei " + invio);
    return invio;
  }
  
  public AllegatoInvioFileSdiSogei retrieveAllegato(Integer codiceInvio, Integer codiceTipoAllegato)
  {
    String hql = "select allegato "
        + "from AllegatoInvioFileSdiSogei allegato "
        + "where allegato.file.codice = :codiceInvio "
        + "and allegato.tipoAllegato.codice = :codiceTipoAllegato "
        + "order by allegato.dataCreazione desc ";
    
    Query q = session.createQuery(hql);
    q.setParameter("codiceInvio", codiceInvio);
    q.setParameter("codiceTipoAllegato", codiceTipoAllegato);
    q.setMaxResults(1);
    
    AllegatoInvioFileSdiSogei invio = (AllegatoInvioFileSdiSogei)q.uniqueResult();
    logger.info("retrieveAllegato returned AllegatoInvioFileSdiSogei " + invio);
    return invio;
  }
  
  public TrasmissioneSogei retrieveTrasmissioneForFlux(Integer codiceInvio)
  {
    String hql = "select tr "
        + "from TrasmissioneSogei tr "
        + "where tr.invio.codice = :codiceInvio ";
    
    Query q = session.createQuery(hql);
    q.setParameter("codiceInvio", codiceInvio);
    q.setMaxResults(1);
    
    TrasmissioneSogei invio = (TrasmissioneSogei)q.uniqueResult();
    logger.info("retrieveTrasmissioneForFlux returned TrasmissioneSogei " + invio);
    return invio;
  }
  
  public List<TrasmissioneSogei> retrieveTrasmissioniForFlux(Integer codiceInvio)
  {
    String hql = "select tr "
        + "from TrasmissioneSogei tr "
        + "where tr.invio.codice = :codiceInvio ";
    
    Query q = session.createQuery(hql);
    q.setParameter("codiceInvio", codiceInvio);
    
    @SuppressWarnings("unchecked")
    List<TrasmissioneSogei> invio = q.list();
    logger.info("retrieveTrasmissioniForFlux returned " + invio.size() + " items for id " + codiceInvio);
    return invio;
  }  
  

  public void sendSegnalazioneForFlusso(InvioFileSdiSogei invio, String errors)
  {
    List<String> to = new ArrayList<String>();
    String emittente = null;
    
    StatoInvioSogei statoInvio = invio.getStatoInvio();
    
    JndiServiceLocator jl = JndiServiceLocator.getInstance();
    
    Object host = null;
    try
    {
      host = jl.lookup("mail/Session");
    }
    catch (Exception e)
    {
      host = null;
    }
    
    if (host == null)
      return;
    
    TrasmissioneSogei trasmissione = retrieveTrasmissioneForFlux(invio.getCodice());
    if (trasmissione != null)
    {
        SoggettoSogei soggetto = trasmissione.getSoggettoCedente();
        if (soggetto != null)
          to.add(soggetto.getMail());
    }
    
    // Prepare load email.
    //
    MailUtils mu = new MailUtils();
    mu.setTemplate("loadxmlflussosogei");
    mu.getContext().put("to", to);
    mu.getContext().put("emittente", emittente);
    mu.getContext().put("errors", errors);
    mu.getContext().put("invio", invio);
    mu.getContext().put("data", new Date());
    mu.getContext().put("stato", statoInvio);
    Message message = mu.buildMessage();

    // Send load email.
    //
    try
    {
      mu.send(message);
      LogUtils.info(getClass(), "Email stats for loading SDI successfully sent.");
    }
    catch(Exception e)
    {
      LogUtils.error(getClass(), "Exception caught while sending email.", e);
      throw new FacadeException(e);
    }
    
  }
  
  public void saveEventoFlusso(Integer codiceFlusso, String descrizioneEvento)
  {
    InvioFileSdiSogei invio = (InvioFileSdiSogei) session.load(InvioFileSdiSogei.class, codiceFlusso);
    StatoInvioSogei stato = invio.getStatoInvio();
    
    EventoSogei evento = new EventoSogei();
    evento.setData(new Date());
    evento.setInvio(invio);
    evento.setDescrizione(descrizioneEvento);
    evento.setStatoLotto(stato);
    
    session.save(evento);
  }
  
  public void saveEventoFlusso(InvioFileSdiSogei invio, String descrizioneEvento)
  {
    StatoInvioSogei stato = invio.getStatoInvio();
    
    EventoSogei evento = new EventoSogei();
    evento.setData(new Date());
    evento.setInvio(invio);
    evento.setDescrizione(descrizioneEvento);
    evento.setStatoLotto(stato);
    
    session.save(evento);
  }
  
  public InvioFileSdiSogei retrieveActiveFluxByIdentificativoSdi(BigInteger identificativo)
  {
    String hql = "from InvioFileSdiSogei iv "
                  + "left join fetch iv.statoInvio st " 
                  + "where iv.identificativo = :identificativo "
                  + "and st.codice in (:statoInviato, :statoRicevuto) ";
    Query q = session.createQuery(hql);
    q.setMaxResults(1);
    q.setParameter("identificativo", identificativo);
    q.setParameter("statoInviato", StatoInvioSogei.INVIATO);
    q.setParameter("statoRicevuto", StatoInvioSogei.RICEVUTO);
    InvioFileSdiSogei invio = (InvioFileSdiSogei)q.uniqueResult();
    
    logger.info("retrieveActiveFluxByIdentificativoSdi returned " + invio + " for id_sdi " + identificativo);
    return invio;
  }
  
  public boolean hasFluxInState(BigInteger identificativo, Integer codiceStatoFlusso)
  {
    String hql = "select count(*) from InvioFileSdiSogei iv "
                  + "where iv.identificativo = :identificativo "
                  + "and iv.statoInvio.codice = :codiceStatoFlusso ";
    Query q = session.createQuery(hql);
    q.setParameter("identificativo", identificativo);
    q.setParameter("codiceStatoFlusso", codiceStatoFlusso);
    
    Long count = (Long) q.uniqueResult();
    boolean res = count.intValue() > 0;
    
    logger.info("hasFluxInState returned " + res + " for id_sdi " + identificativo + " and id_state " + codiceStatoFlusso);
    return res;
  }
  
  public boolean hasTipoNotifica(BigInteger identificativo, Integer codiceTipoNotifica)
  {
    String hql = "select count(*) "
        + "from NotificaSogei ns "
        + "inner join iv.invio iv "
        + "where iv.identificativo = :identificativo "
        + "and ns.tipoNotifica.codice = :codiceStatoFlusso ";
    Query q = session.createQuery(hql);
    q.setParameter("identificativo", identificativo);
    q.setParameter("codiceTipoNotifica", codiceTipoNotifica);
    
    Long count = (Long) q.uniqueResult();
    boolean res = count.intValue() > 0;
    
    logger.info("hasTipoNotifica returned " + res + " for id_sdi " + identificativo + " and id_tipo " + codiceTipoNotifica);
    return res;
  }
  
}
