package dao;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.DateType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.MultiValueMap;

import bean.AppVariables;
import bean.PianoEstrattoreDistinte;
import common.dao.GenericDAO;
import common.dao.IDAO;
import sicura.entities.DistintaFlussiInput;
import sicura.entities.IstruzioniEstrazioneDistinteBanca;
import sicura.entities.PianiEstrazioneDistinteBanca;

@Repository
public class PianiEstrazioneDistinteBancaDAO 
			extends GenericDAO<PianiEstrazioneDistinteBanca, Integer> 
			implements IDAO<PianiEstrazioneDistinteBanca, Integer> {
	
	@Autowired
	IstruzioniEstrazioneDistinteBancaDAO istruzioniDAO;
	
	public List<PianiEstrazioneDistinteBanca> list() {
		boolean tx = startTransaction();
		try {
		
			Criteria crit = currentSession().createCriteria(PianiEstrazioneDistinteBanca.class);
			crit.addOrder(Order.asc("id"));
			
			@SuppressWarnings("unchecked")
			List<PianiEstrazioneDistinteBanca> res = crit.list();
			
			return res;
		} finally {
			if (tx)
				tx = commit();
		}
	}
	
	

	
	public PianoEstrattoreDistinte caricaPianoEstrattore(Integer id) {
		boolean tx = startTransaction();
		try {
			PianoEstrattoreDistinte piano = new PianoEstrattoreDistinte();
			PianiEstrazioneDistinteBanca pianoEstrazione = read(id);
			piano.setPiano(pianoEstrazione);
			
			return piano;
		} finally {
			if (tx)
				tx = commit();
		}
	}

	public List<IstruzioniEstrazioneDistinteBanca> getIstruzioni(Integer id) {
		boolean tx = startTransaction();
		try {
			Criteria crit = currentSession().createCriteria(IstruzioniEstrazioneDistinteBanca.class);
			crit.add(Restrictions.eq("idpianoEstrazione", id))
				.addOrder(Order.asc("rowNumber"));
			
			List<IstruzioniEstrazioneDistinteBanca> res = crit.list();
			
			return res;
		} finally {
			if (tx)
				tx = commit();
		}
	}

	public IstruzioniEstrazioneDistinteBanca getNewIstruzione(Integer id) {
		IstruzioniEstrazioneDistinteBanca res = new IstruzioniEstrazioneDistinteBanca();
		res.setId(0);
		res.setIdpianoEstrazione(id);
		res.setRowNumber(countIstruzioni(id)+1);
		return res;
	}

	private int countIstruzioni(Integer id) {
		if (id==null)
			return 0;
		//boolean tx = startTransaction();
		try{
			String sql = "select coalesce(max (rowNumber),0) from IstruzioniEstrazioneDistinteBanca where idPianoEstrazione=" + id;
			Integer res = (Integer) executeGenericQuerySingleRow(sql);
			return res;
		} finally {
//			if (tx)
//				tx = commit();
		}
	}

	public String execute(Integer idPiano, AppVariables appVariables) {

		/*
		  CREATE PROCEDURE [dbo].[spEstraiByPiano]
			@SecurityUserId VARCHAR(15),
			@SecurityGuid UNIQUEIDENTIFIER,
		
			@PianoID int,
			@UserID varchar(10) = null,
			@DenominazioneUtente varchar(50) = 'Sistema'
		 */

		Integer res = -1;
		boolean tx = startTransaction();
		try {
			
			Connection connection = getConnection();
			CallableStatement proc;
			try {
				proc = connection.prepareCall("{? = call spEstraiByPiano (?,?,?,?,?)}");
					
				proc.registerOutParameter(1, Types.INTEGER);
				proc.setString(2, appVariables.getUserId());
				proc.setString(3, appVariables.getGuid());
				proc.setObject(4, idPiano);
				proc.setString(5,  appVariables.getUserId());
				proc.setString(6,  appVariables.getDenominazioneUtente());
	
				proc.execute();
				
				res = new Integer(proc.getInt(1));
					
			} catch (SQLException e) {
				tx =rollback();
				e.printStackTrace();
				return e.getMessage();
			}
			
			return res.toString();
		} finally {
			if (tx)
				tx = commit();
		}
	}

	public Integer saveNoTransaction(PianiEstrazioneDistinteBanca pianoEstrazione,AppVariables appVariables) throws Exception{
		/*
		 CREATE PROC [dbo].[spUCBase_PianiEstrazioneDistinteBanca_update]
				@SecurityUserId VARCHAR(15),
				@SecurityGuid UNIQUEIDENTIFIER,
			
				@ID int,
				@Denominazione varchar(50),
				@Enabled bit,
				@ScheduledDay1 bit,
				@ScheduledDay2 bit,
				@ScheduledDay3 bit,
				@ScheduledDay4 bit,
				@ScheduledDay5 bit,
				@ScheduledDay6 bit,
				@ScheduledDay7 bit,
				@StartTime datetime,
				@StatoDisposizioneDaEstrarre varchar(15),
				@CutOffDataCreazioneDisposizione datetime,
				@StatusLastExecution int,
				@LastExecution datetime,
				@IDContoDefault1 int,
				@IDContoDefault2 int,
				@UsedByService bit,
				@ABIOrdinante varchar(5),
				@UsaTipoSequenzaRID BIT = 0
		 */
		
		Integer res = null;
		try {
			Connection connection = getConnection();
			
			CallableStatement proc;
			proc = connection.prepareCall("{? = call spUCBase_PianiEstrazioneDistinteBanca_update (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}");
				
			if (pianoEstrazione.getId()==null)
				pianoEstrazione.setId(0);
			
			proc.registerOutParameter(1, Types.VARCHAR);
			proc.setString(2, appVariables.getUserId());
			proc.setString(3, appVariables.getGuid());
			proc.setObject(4, pianoEstrazione.getId());
			proc.setString(5, pianoEstrazione.getDenominazione());
			proc.setBoolean(6, pianoEstrazione.isEnabled());
			proc.setBoolean(7, pianoEstrazione.isScheduledDay1());
			proc.setBoolean(8, pianoEstrazione.isScheduledDay2());
			proc.setBoolean(9, pianoEstrazione.isScheduledDay3());
			proc.setBoolean(10, pianoEstrazione.isScheduledDay4());
			proc.setBoolean(11, pianoEstrazione.isScheduledDay5());
			proc.setBoolean(12, pianoEstrazione.isScheduledDay6());
			proc.setBoolean(13, pianoEstrazione.isScheduledDay7());
			proc.setTimestamp(14, dateToSqlTimestamp(pianoEstrazione.getStartTime()));
			proc.setString(15, pianoEstrazione.getStatoDisposizioneDaEstrarre());
			proc.setTimestamp(16, dateToSqlTimestamp(pianoEstrazione.getCutOffDataCreazioneDisposizione()));
			proc.setObject(17,pianoEstrazione.getStatusLastExecution());
			proc.setDate(18, dateToSqlDate(pianoEstrazione.getLastExecution()));
			proc.setObject(19, pianoEstrazione.getIdcontoDefault1());
			proc.setObject(20, pianoEstrazione.getIdcontoDefault2());
			proc.setBoolean(21, pianoEstrazione.isUsedByService());
			proc.setString(22, pianoEstrazione.getAbiordinante());
			proc.setBoolean(23, pianoEstrazione.isUsaTipoSequenzaRid());
			
			proc.execute();
			proc.getMoreResults();
				
			res = proc.getInt(1);
				
		} catch (Exception ex) {
			throw ex;
		} 

		return res;

	}

	public Integer delete(Integer id, AppVariables appVariables) {
		/*
		 CREATE PROC [dbo].[spUCBase_PianiEstrazioneDistinteBanca_delete]
			@SecurityUserId VARCHAR(15),
			@SecurityGuid UNIQUEIDENTIFIER,
		
			@ID int
		 */
		Integer res = null;
		boolean tx = startTransaction();
		try {
			try {
				Connection connection = getConnection();
				
				deleteIstruzioni(id, appVariables);
				
				CallableStatement proc;
				proc = connection.prepareCall("{? = call spUCBase_PianiEstrazioneDistinteBanca_delete (?,?,?)}");
					
				proc.registerOutParameter(1, Types.VARCHAR);
				proc.setString(2, appVariables.getUserId());
				proc.setString(3, appVariables.getGuid());
				proc.setObject(4,id);
				
				proc.execute();
				proc.getMoreResults();
					
				res = proc.getInt(1);
					
			} catch (Exception ex) {
				res = -1;
			} 
		
		} finally {
			if (tx)
				commit();
		}
		return res;
	}




	private void deleteIstruzioni(Integer id, AppVariables appVariables) throws SQLException {
		/* 
		  CREATE PROC [dbo].[spUCBase_IstruzioniEstrazioneDistinteBanca_delete]
			@SecurityUserId VARCHAR(15),
			@SecurityGuid UNIQUEIDENTIFIER,
		
			@ID int
		 */
		
		
		List<IstruzioniEstrazioneDistinteBanca> istruzioni = istruzioniDAO.getIstruzioniNoTrasaction(id);
		Connection connection = getConnection();
		CallableStatement proc;
		proc = connection.prepareCall("{? = call spUCBase_IstruzioniEstrazioneDistinteBanca_delete (?,?,?)}");
			
		for(IstruzioniEstrazioneDistinteBanca istruzione: istruzioni) {
			proc.registerOutParameter(1, Types.VARCHAR);
			proc.setString(2, appVariables.getUserId());
			proc.setString(3, appVariables.getGuid());
			proc.setObject(4,istruzione.getId());
			
			proc.execute();
			proc.getMoreResults();
		}
		
		
			
	}
}
