package siprp.logic;

import static com.evolute.utils.strings.UnicodeLatin1Map.atilde;
import static com.evolute.utils.strings.UnicodeLatin1Map.ccedil;
import static com.evolute.utils.strings.UnicodeLatin1Map.iacute;

import java.util.HashMap;
import java.util.List;

import javax.swing.tree.DefaultMutableTreeNode;

import leaf.ui.LeafDialog;
import leaf.ui.TreeTools;
import siprp.database.cayenne.objects.Empresas;
import siprp.database.cayenne.objects.Estabelecimentos;
import siprp.database.cayenne.objects.HsArea;
import siprp.database.cayenne.objects.HsEmailEstabelecimento;
import siprp.database.cayenne.objects.HsEquipamento;
import siprp.database.cayenne.objects.HsLegislacao;
import siprp.database.cayenne.objects.HsLegislacaoCategoria;
import siprp.database.cayenne.objects.HsLegislacaoEmpresa;
import siprp.database.cayenne.objects.HsLegislacaoEstabelecimento;
import siprp.database.cayenne.objects.HsNormalizacao;
import siprp.database.cayenne.objects.HsNormalizacaoEmpresa;
import siprp.database.cayenne.objects.HsNormalizacaoEstabelecimento;
import siprp.database.cayenne.objects.HsPosto;
import siprp.database.cayenne.objects.HsPostoEstabelecimento;
import siprp.database.cayenne.objects.HsPostoRisco;
import siprp.database.cayenne.objects.HsRelatorio;
import siprp.database.cayenne.objects.HsRelatorioArea;
import siprp.database.cayenne.objects.HsRelatorioLegislacao;
import siprp.database.cayenne.objects.HsRelatorioMedida;
import siprp.database.cayenne.objects.HsRelatorioNormalizacao;
import siprp.database.cayenne.objects.HsRelatorioPosto;
import siprp.database.cayenne.objects.HsRelatorioPostoMedida;
import siprp.database.cayenne.objects.HsRelatorioPostoRisco;
import siprp.database.cayenne.objects.HsRelatorioRisco;
import siprp.database.cayenne.objects.HsRelatorioRiscoValorQualitativo;
import siprp.database.cayenne.objects.HsRisco;
import siprp.database.cayenne.objects.HsRiscoEmpresa;
import siprp.database.cayenne.objects.HsRiscoMedida;
import siprp.database.cayenne.objects.HsRiscoTema;
import siprp.database.cayenne.providers.MedicinaDAO;
import siprp.database.cayenne.providers.PlanoActuacaoDAO;
import siprp.logic.node.AreaNode;
import siprp.logic.node.AreaRelatorioNode;
import siprp.logic.node.NodeMedida;
import siprp.logic.node.NodeRisco;
import siprp.logic.node.NodeRiscoTema;
import siprp.logic.node.PostoNode;
import siprp.logic.node.PostoRelatorioNode;

public class HigieneSegurancaLogic
{

	private static final PlanoActuacaoDAO planoProvider = new PlanoActuacaoDAO();
	
	private static final MedicinaDAO medicinaProvider = new MedicinaDAO();
	
	public static DefaultMutableTreeNode getRiscosTree()
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		List<HsRiscoTema> temas = planoProvider.getAllRiscoTemas();
		if( temas != null )
		{
			for( HsRiscoTema tema : temas )
			{
				NodeRiscoTema temaNode = new NodeRiscoTema( tema );
				for( HsRisco risco : tema.getHsRiscoArray() )
				{
					NodeRisco riscoNode = new NodeRisco( risco );
					for( HsRiscoMedida rel : risco.getHsRiscoMedidaArray() )
					{
						riscoNode.add( new NodeMedida( rel ) );
					}
					temaNode.add( riscoNode );
				}
				result.add( temaNode );
			}
		}
		return result;
	}
	
	public static DefaultMutableTreeNode getRiscosTree( Empresas empresa )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		for( HsRiscoEmpresa rel : empresa.getHsRiscoEmpresaArray() )
		{
			HsRisco risco = rel.getToHsRisco();
			HsRiscoTema tema = risco.getToHsRiscoTema();
			DefaultMutableTreeNode temaNode = TreeTools.findNodeWithUserObject( tema, result );
			if( temaNode == null )
			{
				temaNode = new NodeRiscoTema( tema );
				result.add(temaNode);
			}
			temaNode.add( new NodeRisco( risco ) );
		}
		return result;
	}
	
	public static DefaultMutableTreeNode getAreasTree( Empresas empresa )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		if( empresa != null )
		{
			for( HsArea area : empresa.getHsAreaArray() )
			{
				AreaNode areaNode = new AreaNode(area);
				for( HsPosto posto : area.getHsPostoArray() )
				{
					areaNode.add( new PostoNode( posto ) );
				}
				result.add( areaNode );
			}
		}
		return result;
	}

	public static DefaultMutableTreeNode getAreasTree( Estabelecimentos estabelecimento )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		if( estabelecimento != null )
		{
			List<HsPostoEstabelecimento> postos = estabelecimento.getHsPostoEstabelecimentoArray();
			for( HsPostoEstabelecimento rel : postos )
			{
				HsPosto posto = rel.getToHsPosto();
				HsArea area = posto.getToHsArea();
				DefaultMutableTreeNode areaNode = TreeTools.findNodeWithUserObject( area, result );
				if( areaNode == null )
				{
					areaNode = new AreaNode( area );
					result.add( areaNode );
				}
				areaNode.add( new PostoNode( posto ) );
			}
			TreeTools.sort( result );
		}
		return result;
	}
	
	public static DefaultMutableTreeNode getPostosTree( Estabelecimentos estabelecimento )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		if( estabelecimento != null )
		{
			List<HsPostoEstabelecimento> postos = estabelecimento.getHsPostoEstabelecimentoArray();
			for( HsPostoEstabelecimento rel : postos )
			{
				result.add( new PostoNode( rel.getToHsPosto() ) );
			}
		}
		return result;
	}

	public static List<Empresas> getAllEmpresas()
	{
		return medicinaProvider.getAllEmpresas();
	}

	public static List<HsRelatorioRiscoValorQualitativo> getAllValoresQualitativos()
	{
		return planoProvider.getAllValoresQualitativos();
	}

	public static DefaultMutableTreeNode getAreasRelatorioTree( HsRelatorio relatorio )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		if( relatorio != null )
		{
			for( HsRelatorioArea area : relatorio.getHsRelatorioArea() )
			{
				AreaRelatorioNode areaNode = new AreaRelatorioNode(area);
				for( HsRelatorioPosto posto : area.getHsRelatorioPostoArray() )
				{
					areaNode.add( new PostoRelatorioNode( posto ) );
				}
				result.add( areaNode );
			}
		}
		return result;
	}

	public static void reverterRelatorio( HsRelatorio relatorio )
	{
		try
		{
			if(relatorio != null)
			{
				Estabelecimentos estabelecimento = relatorio.getToHsMarcacoesEstabelecimento() == null ? null : relatorio.getToHsMarcacoesEstabelecimento().getToEstabelecimentos();
				if( estabelecimento != null )
				{
					reverterAreas( relatorio, estabelecimento );
					reverterLegislacao( relatorio, estabelecimento ); 
					reverterNormalizacao( relatorio, estabelecimento );
				}
			}
		} catch( Exception e )
		{
			LeafDialog.error(e);
		}
	}
	
	private static void reverterAreas( HsRelatorio relatorio, Estabelecimentos estabelecimento ) throws Exception
	{
		List<HsRelatorioArea> areas = relatorio.getHsRelatorioArea();
		int areasSize = areas == null ? 0 : areas.size();
		for( int i = 0; i < areasSize; ++i )
		{
			areas.get( 0 ).delete();
		}
		relatorio.save();
		List<HsPostoEstabelecimento> postos = estabelecimento.getHsPostoEstabelecimentoArray();
		reverterPostos(relatorio,postos);
		relatorio.save();
	}
	
	private static void reverterPostos( HsRelatorio relatorio, List<HsPostoEstabelecimento> postos )
	{
		HashMap<HsArea,HsRelatorioArea> areasInserted = new HashMap<HsArea, HsRelatorioArea>();
		for( HsPostoEstabelecimento rel : postos )
		{
			HsPosto posto = rel.getToHsPosto();
			HsRelatorioPosto rPosto = new HsRelatorioPosto();
			rPosto.setDescription( posto.getDescription() );
			HsArea area = posto.getToHsArea();
			HsRelatorioArea rArea = areasInserted.get( area );
			if( rArea == null )
			{
				rArea = new HsRelatorioArea();
				rArea.setDescription( area.getDescription() );
				rArea.setToHsRelatorio( relatorio );
				areasInserted.put(area,rArea);
			}
			rPosto.setToHsRelatorioArea( rArea );
			addMedidasAndRiscos(posto,rPosto);
		}
	}
	
	private static void addMedidasAndRiscos(HsPosto posto, HsRelatorioPosto rPosto)
	{
		for( HsPostoRisco postoRisco : posto.getHsPostoRiscoArray() )
		{
			HsRelatorioRisco rRelatorioRisco = new HsRelatorioRisco();
			rRelatorioRisco.setToHsRelatorio( rPosto.getToHsRelatorioArea().getToHsRelatorio() );
			rRelatorioRisco.setDescription( postoRisco.getToHsRisco().getDescription() );
			HsRelatorioPostoRisco rPostoRisco = new HsRelatorioPostoRisco();
			rPostoRisco.setToHsRelatorioPosto( rPosto );
			rPostoRisco.setToHsRelatorioRisco( rRelatorioRisco );
			for( HsRiscoMedida riscoMedida : postoRisco.getToHsRisco().getHsRiscoMedidaArray() )
			{
				HsRelatorioMedida rMedida = new HsRelatorioMedida();
				rMedida.setDescription( riscoMedida.getToHsMedida().getDescription() );
				rMedida.setRequesitosLegais( riscoMedida.getToHsMedida().getRequesitosLegais() );
				rMedida.setToHsRelatorioRisco( rRelatorioRisco );
				HsRelatorioPostoMedida rPostoMedida = new HsRelatorioPostoMedida();
				rPostoMedida.setIsPlanoActuacao( false );
				rPostoMedida.setToHsRelatorioMedida( rMedida );
				rPostoMedida.setToHsRelatorioPosto( rPosto );
			}
		}
	}

	private static void reverterLegislacao( HsRelatorio relatorio, Estabelecimentos estabelecimento ) throws Exception
	{
		for(HsRelatorioLegislacao legislacao : relatorio.getHsRelatorioLegislacaoArray())
		{
			legislacao.delete();
		}
		for( HsLegislacaoEstabelecimento rel : estabelecimento.getHsLegislacaoEstabelecimentoArray() )
		{
			HsLegislacao legislacao = rel.getToHsLegislacao();
			HsRelatorioLegislacao relatorioLegislacao = criarRelatorioLegislacao( relatorio, legislacao );
			relatorioLegislacao.save();
		}
	}
	
	private static HsRelatorioLegislacao criarRelatorioLegislacao( HsRelatorio relatorio, HsLegislacao legislacao )
	{
		HsRelatorioLegislacao result = null;
		if( relatorio != null && legislacao != null )
		{
			result = new HsRelatorioLegislacao();
			result.setCategoria( legislacao.getToHsLegislacaoCategoria() == null ? null : legislacao.getToHsLegislacaoCategoria().getDescription() );
			result.setToHsRelatorio( relatorio );
			result.setHsLegislacaoId( legislacao.getId() );
			result.setDescricao( legislacao.getDescription() );
		}
		return result;
	}
	
	private static void reverterNormalizacao( HsRelatorio relatorio, Estabelecimentos estabelecimento ) throws Exception
	{
		for(HsRelatorioNormalizacao normalizacao : relatorio.getHsRelatorioNormalizacaoArray() )
		{
			normalizacao.delete();
		}
		for( HsNormalizacaoEstabelecimento rel : estabelecimento.getHsNormalizacaoEstabelecimentoArray() )
		{
			HsNormalizacao normalizacao = rel.getToHsNormalizacao();
			HsRelatorioNormalizacao relatorioNormalizacao = criarRelatorioNormalizacao( relatorio, normalizacao );
			relatorioNormalizacao.save();
		}
	}
	
	private static HsRelatorioNormalizacao criarRelatorioNormalizacao( HsRelatorio relatorio, HsNormalizacao normalizacao )
	{
		HsRelatorioNormalizacao result = null;
		if( relatorio != null && normalizacao != null )
		{
			result = new HsRelatorioNormalizacao();
			result.setCodigo( normalizacao.getCodigo() );
			result.setDescricao( normalizacao.getDescricao() );
			result.setToHsRelatorio( relatorio );
			result.setHsNormalizacaoId( normalizacao.getId() );
			result.setPortuguesa( normalizacao.getPortuguesa() );
		}
		return result;
	}
	
	public static boolean isProbabilidadeValida( Integer probabilidade )
	{
		return probabilidade != null && probabilidade > 0 && probabilidade < 17;
	}
	
	public static boolean isSeveridadeValida( Integer severidade )
	{
		return severidade != null && severidade > 0 && severidade < 17;
	}

	public static boolean isRelatorioRiscoPreenchido( HsRelatorioPostoRisco rel )
	{
		boolean hasQual = rel.getToHsRelatorioRiscoValorQualitativo() != null;
		boolean hasQuant = false;
		if( !hasQual )
		{
			hasQuant = HigieneSegurancaLogic.isSeveridadeValida( rel.getSeveridade() );
			hasQuant &= HigieneSegurancaLogic.isProbabilidadeValida( rel.getSeveridade() );
		}
		return hasQual || hasQuant;
	}

	public static DefaultMutableTreeNode getLegislacaoGeral()
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		for( HsLegislacao legislacao : planoProvider.getAllLegislacaoGeral() )
		{
			DefaultMutableTreeNode legislacaoNode = new DefaultMutableTreeNode( legislacao );
			result.add( legislacaoNode );
		}
		return result;
	}

	public static DefaultMutableTreeNode getLegislacaoEspecifica()
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		for( HsLegislacaoCategoria categoria : planoProvider.getAllLegislacaoCategorias() )
		{
			DefaultMutableTreeNode categoriaNode = new DefaultMutableTreeNode( categoria );
			for( HsLegislacao legislacao: categoria.getHsLegislacaoArray() )
			{
				if( legislacao.getDeletedDate() == null )
				{
					DefaultMutableTreeNode legislacaoNode = new DefaultMutableTreeNode( legislacao );
					categoriaNode.add( legislacaoNode );
				}
			}
			result.add( categoriaNode );
		}
		return result;
	}

	public static DefaultMutableTreeNode getNormalizacaoTree( boolean portuguesa )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode("Normaliza" + ccedil + atilde + "o " + ( portuguesa ? "Portuguesa" : "Internacional" ) );
		for( HsNormalizacao normalizacao : planoProvider.getNormalizacao( portuguesa ) )
		{
			DefaultMutableTreeNode normalizacaoNode = new DefaultMutableTreeNode( normalizacao );
			result.add( normalizacaoNode );
		}
		return result;
	}
	
	public static DefaultMutableTreeNode getNormalizacaoTreeForEmpresa( Empresas empresa )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		DefaultMutableTreeNode portuguesa = new DefaultMutableTreeNode("Normaliza" + ccedil + atilde + "o Portuguesa" );
		DefaultMutableTreeNode internacional = new DefaultMutableTreeNode("Normaliza" + ccedil + atilde + "o Internacional" );
		for( HsNormalizacao normalizacao : planoProvider.getNormalizacao( true ) )
		{
			if( empresa == null || hasEmpresa( normalizacao, empresa ) )
			{
				DefaultMutableTreeNode normalizacaoNode = new DefaultMutableTreeNode( normalizacao );
				portuguesa.add( normalizacaoNode );
			}
		}
		for( HsNormalizacao normalizacao : planoProvider.getNormalizacao( false ) )
		{
			if( empresa == null || hasEmpresa( normalizacao, empresa ) )
			{
				DefaultMutableTreeNode normalizacaoNode = new DefaultMutableTreeNode( normalizacao );
				internacional.add( normalizacaoNode );
			}
		}
		result.add( portuguesa );
		result.add( internacional );
		return result;
	}
	
	private static boolean hasEmpresa( HsNormalizacao normalizacao, Empresas empresa )
	{
		boolean result = false;
		if( normalizacao != null && empresa != null  )
		{
			for( HsNormalizacaoEmpresa rel : normalizacao.getHsNormalizacaoEmpresaArray())
			{
				result = empresa.equals( rel.getToEmpresa() );
				if( result )
				{
					break;
				}
			}
		}
		return result;
	}
	
	public static DefaultMutableTreeNode getNormalizacaoTreeForEstabelecimento( Estabelecimentos estabelecimento )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		DefaultMutableTreeNode portuguesa = new DefaultMutableTreeNode("Normaliza" + ccedil + atilde + "o Portuguesa" );
		DefaultMutableTreeNode internacional = new DefaultMutableTreeNode("Normaliza" + ccedil + atilde + "o Internacional" );
		for( HsNormalizacao normalizacao : planoProvider.getNormalizacao( true ) )
		{
			if( estabelecimento == null || hasEstabelecimento( normalizacao, estabelecimento ) )
			{
				DefaultMutableTreeNode normalizacaoNode = new DefaultMutableTreeNode( normalizacao );
				portuguesa.add( normalizacaoNode );
			}
		}
		for( HsNormalizacao normalizacao : planoProvider.getNormalizacao( false ) )
		{
			if( estabelecimento == null || hasEstabelecimento( normalizacao, estabelecimento ) )
			{
				DefaultMutableTreeNode normalizacaoNode = new DefaultMutableTreeNode( normalizacao );
				internacional.add( normalizacaoNode );
			}
		}
		result.add( portuguesa );
		result.add( internacional );
		return result;
	}
	
	private static boolean hasEstabelecimento( HsNormalizacao normalizacao, Estabelecimentos estabelecimento )
	{
		boolean result = false;
		if( normalizacao != null && estabelecimento != null  )
		{
			for( HsNormalizacaoEstabelecimento rel : normalizacao.getHsNormalizacaoEstabelecimentoArray())
			{
				result = estabelecimento.equals( rel.getToEstabelecimento() );
				if( result )
				{
					break;
				}
			}
		}
		return result;
	}
	
	public static DefaultMutableTreeNode getLegislacaoTreeForEmpresa( Empresas empresa )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		DefaultMutableTreeNode geral = new DefaultMutableTreeNode( "Legisla" + ccedil + atilde + "o de aplica" + ccedil + atilde + "o geral" );
		DefaultMutableTreeNode especifica = new DefaultMutableTreeNode( "Legisla" + ccedil + atilde + "o espec" + iacute + "fica" );
		for( HsLegislacao legislacao : planoProvider.getAllLegislacaoGeral() )
		{
			if( empresa == null || hasEmpresa( legislacao, empresa ) )
			{
				DefaultMutableTreeNode legislacaoNode = new DefaultMutableTreeNode( legislacao );
				geral.add( legislacaoNode );
			}
		}
		for( HsLegislacaoCategoria categoria : planoProvider.getAllLegislacaoCategorias( ) )
		{
			boolean addCategory = false;
			DefaultMutableTreeNode categoriaNode = new DefaultMutableTreeNode( categoria );
			for( HsLegislacao legislacao : categoria.getHsLegislacaoArray() )
			{
				if( empresa == null || hasEmpresa( legislacao, empresa ) )
				{
					DefaultMutableTreeNode legislacaoNode = new DefaultMutableTreeNode( legislacao );
					categoriaNode.add( legislacaoNode );
					addCategory = true;
				}
				
			}
			if( addCategory)
			{
				especifica.add( categoriaNode );
			}
		}
		result.add( geral );
		result.add( especifica );
		return result;
	}
	
	private static boolean hasEmpresa( HsLegislacao legislacao, Empresas empresa )
	{
		boolean result = false;
		if( legislacao != null && empresa != null  )
		{
			for( HsLegislacaoEmpresa rel : legislacao.getHsLegislacaoEmpresaArray() )
			{
				result = empresa.equals( rel.getToHsEmpresa() );
				if( result )
				{
					break;
				}
			}
		}
		return result;
	}

	public static DefaultMutableTreeNode getLegislacaoTreeForEstabelecimento( Estabelecimentos estabelecimento )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		DefaultMutableTreeNode geral = new DefaultMutableTreeNode( "Legisla" + ccedil + atilde + "o de aplica" + ccedil + atilde + "o geral" );
		DefaultMutableTreeNode especifica = new DefaultMutableTreeNode( "Legisla" + ccedil + atilde + "o espec" + iacute + "fica" );
		for( HsLegislacao legislacao : planoProvider.getAllLegislacaoGeral() )
		{
			if( estabelecimento == null || hasEstabelecimento( legislacao, estabelecimento ) )
			{
				DefaultMutableTreeNode legislacaoNode = new DefaultMutableTreeNode( legislacao );
				geral.add( legislacaoNode );
			}
		}
		for( HsLegislacaoCategoria categoria : planoProvider.getAllLegislacaoCategorias( ) )
		{
			boolean addCategory = false;
			DefaultMutableTreeNode categoriaNode = new DefaultMutableTreeNode( categoria );
			for( HsLegislacao legislacao : categoria.getHsLegislacaoArray() )
			{
				if( estabelecimento == null || hasEstabelecimento( legislacao, estabelecimento ) )
				{
					DefaultMutableTreeNode legislacaoNode = new DefaultMutableTreeNode( legislacao );
					categoriaNode.add( legislacaoNode );
					addCategory = true;
				}
				
			}
			if( addCategory)
			{
				especifica.add( categoriaNode );
			}
		}
		result.add( geral );
		result.add( especifica );
		return result;
	}
	
	private static boolean hasEstabelecimento( HsLegislacao legislacao, Estabelecimentos estabelecimento )
	{
		boolean result = false;
		if( legislacao != null && estabelecimento != null  )
		{
			for( HsLegislacaoEstabelecimento rel : legislacao.getHsLegislacaoEstabelecimentoArray() )
			{
				result = estabelecimento.equals( rel.getToHsEstabelecimento());
				if( result )
				{
					break;
				}
			}
		}
		return result;
	}

	public static DefaultMutableTreeNode getEquipamentosTree()
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		List<HsEquipamento> equipamentos = planoProvider.getAllEquipamentos();
		if( equipamentos != null )
		{
			for( HsEquipamento equipamento : equipamentos )
			{
				result.add( new DefaultMutableTreeNode( equipamento ) );
			}
		}
		return result;
	}

	public static DefaultMutableTreeNode getEmailsForEstabelecimento( Estabelecimentos estabelecimento )
	{
		DefaultMutableTreeNode result = new DefaultMutableTreeNode();
		List<HsEmailEstabelecimento> emails = planoProvider.getEmailsForEstabelecimento( estabelecimento );
		if( emails != null )
		{
			for( HsEmailEstabelecimento rel : emails )
			{
				result.add( new DefaultMutableTreeNode( rel ) );
			}
		}
		return result;
	}
	
}
