
/**
 * Abstract class Seguradora - write a description of the class here
 * 
 * @author FMM
 * @version (version number or date here)
 */
import java.io.Serializable;
import java.util.*;
import java.io.PrintWriter;
import java.io.IOException;
public class Seguradora_Exame implements Serializable {

    // Variáveis e métodos de instância
    
    // Decisão: Cada uma das BDs indexa a outra, ou seja, cada cliente vai possuir
    // um conjunto de códigos de seguros de que é titular, e cada seguro possui o
    // código do cliente que é o seu titular
    
    
    private TreeMap<String, Cliente> clientes = new TreeMap<String, Cliente>();
    private TreeMap<String, Seguro> seguros = new TreeMap<String, Seguro>(); 
    private GregorianCalendar dataSistema = null;   // data de referência da seguradora
    private TreeSet<String> nomesSeguros = new TreeSet<String>();      // tipos de seguros
   
    // Construtores
  
    public Seguradora_Exame() {}
    
    public Seguradora_Exame(Seguradora_Exame segura) {
        for(Cliente cli : segura.getClientes().values()) clientes.put(cli.getCodCliente(), cli);
        for(Seguro seg : segura.getSeguros().values()) seguros.put(seg.getCodSeguro(), seg);
        dataSistema = segura.getDataSistema();
    }
    
    public Seguradora_Exame(Map<String, Cliente> clis, Map<String, ? extends Seguro> segs,
                      GregorianCalendar dataSys) {
        for(Cliente cli : clis.values()) clientes.put(cli.getCodCliente(), cli.clone());
        for(Seguro seg : segs.values()) seguros.put(seg.getCodSeguro(), seg.clone());
        dataSistema = (GregorianCalendar) dataSys.clone();
    }
    
    // gets
    
   public GregorianCalendar getDataSistema() { return (GregorianCalendar) dataSistema.clone(); }
    
    public Map<String, Cliente> getClientes() {
         Map<String, Cliente> auxCli = new TreeMap<String, Cliente>();
         for(Cliente cli : clientes.values()) auxCli.put(cli.getCodCliente(), cli.clone()); 
         return auxCli;
    }
    
    public Map<String, Seguro> getSeguros() {
         Map<String, Seguro> auxSeg = new TreeMap<String, Seguro>();
         for(Seguro seg : seguros.values()) auxSeg.put(seg.getCodSeguro(), seg.clone()); 
         return auxSeg;
    }
    
    public Set<String> getNomesSeg() {
        Set<String> auxNomes = new TreeSet<String>();
        for(String nomeSeg : nomesSeguros) auxNomes.add(nomeSeg);
        return auxNomes;
    }
    
    // sets e modificadores
    public void mudaDataSistema(GregorianCalendar dataHoje) {
        dataSistema = (GregorianCalendar) dataHoje.clone();
    }
    
    public void insTipoSeguro(String tpSeg) { nomesSeguros.add(tpSeg); }
    
    // consultas
    
    // numAnos = 1 logo que seguro é realizado
    public boolean segEmAtraso(String codSeg) {
        Seguro seg = seguros.get(codSeg);
        int anoInicio = seg.getDataInicio().get(Calendar.YEAR); 
        GregorianCalendar dataPagamento = seg.getDataInicio();
        dataPagamento.set(Calendar.YEAR, anoInicio + seg.getNumAnos());
        return dataPagamento.before(dataSistema);
    }
  
    public double aReceberEsteMes() {
        int mesActual = dataSistema.get(Calendar.MONTH);
        double aReceber = 0.0;
        for(Seguro seg : seguros.values())
           if(seg.getDataInicio().get(Calendar.MONTH) == mesActual) 
              aReceber += seg.getPrecoBase();
        return aReceber;
    }
    
    // versão mais lógica que percorre tabela de clientes 
    public Map<String, Set<Seguro>> tabClienteSegurosTipo(String tipoSeguro) {
     Map<String, Set<Seguro>> tab = new TreeMap<String, Set<Seguro>>();
     Set<Seguro> auxSeg = null; Seguro seg = null;
     for(Cliente cli : clientes.values()) {
        auxSeg = new HashSet<Seguro>();
        for(String codSeg : cli.getCodSeguros()) {
            seg = seguros.get(codSeg);
            if( (seg.getClass().getName()).equals(tipoSeguro) ) auxSeg.add(seg.clone());
        }
        tab.put(cli.getCodCliente(), auxSeg);
     }
     return tab;
    }
    
    
    // versão menos lógica que percorre tabela de seguros 
    public Map<String, Set<Seguro>> tabClienteSegurosTipo1(String tipoSeguro) {
     Map<String, Set<Seguro>> tab = new TreeMap<String, Set<Seguro>>();
     Set<Seguro> auxSeg = null; String codTit = "";
     for(Seguro seg : seguros.values()) 
        if( (seg.getClass().getName()).equals(tipoSeguro) ) {
            codTit = seg.getCodTitular();
            if(!tab.containsKey(codTit)) tab.put(codTit, new HashSet<Seguro>()); 
            tab.get(codTit).add(seg.clone());
        }
     return tab;
    }
    
    public void gravaSegEmAtraso(String fich) throws IOException {
        PrintWriter pw = new PrintWriter(fich);
        for(Seguro s : seguros.values())
           if(this.segEmAtraso(s.getCodSeguro()) && s.getNumActivEsteAno() > 1)
               pw.println(s);
        pw.flush(); pw.close();
    }
    
    public TreeSet<Seguro> segurosPorAno(int ano) {
        TreeSet<Seguro> segsAno = new TreeSet<Seguro>(new SeguroComparatorCod());
        for(Seguro seg : seguros.values())
           if(seg.getDataInicio().get(Calendar.YEAR) == ano) segsAno.add(seg.clone());
        return segsAno;
    }
    
    public TreeSet<Seguro> segurosPorData(TreeSet<Seguro> segs) {
        TreeSet<Seguro> segsData = new TreeSet<Seguro>(new SeguroComparatorData());
        for(Seguro seg : segs)
           segsData.add(seg.clone());
        return segsData;
    }
    
    public boolean temSegsEmAtraso(String codCli) {
        Iterator<String> codSegs = clientes.get(codCli).getCodSeguros().iterator();
        boolean emAtraso = false; Seguro seg = null;
        while(codSegs.hasNext() && !emAtraso) 
            emAtraso = this.segEmAtraso(codSegs.next());
        return emAtraso;
    }
    
    public double aPagar(String codSeguro) {
        Seguro seg = seguros.get(codSeguro);
        double valor = seg.getPrecoBase();
        int numActiv = seg.getNumActivEsteAno();
        if( numActiv == 0) 
           valor = valor - (valor * seg.getTaxaBonus());
        else
           valor = valor + (valor * seg.getTaxaActiv() * numActiv);
        
        // soma valor das cláusulas
        Set<Clausula> clausulas = seg.todasAsClausulasPagas();
        for(Clausula c : clausulas)
           valor += (valor * c.getTaxaClausula());
        return valor;
    }
        
}
            
    
