package br.edu.ifba.ads.mediaCenter;

import br.edu.ifba.ads.mediaCenter.exceptions.ArquivoNaoArmazenadoException;
import br.edu.ifba.ads.mediaCenter.exceptions.BuscavelNaoEncontradoException;
import br.edu.ifba.ads.mediaCenter.exceptions.FragmentoNaoArmazenadoException;
import br.edu.ifba.ads.mediaCenter.util.Buscador;

public class MediaCenter{
    private Servidor[] servidores;
    private Arquivo[] arquivos;    
    
    
    public MediaCenter(){
        this.servidores = new Servidor[0];
        this.arquivos = new Arquivo[0];        
    }    

    public double getTempoArmazenamento(Arquivo arquivo) 
    		throws ArquivoNaoArmazenadoException{
        double tempo = 0;
        try{
	        Fragmento[] fragmentos = arquivo.getOrdenadoPorTamanho();
	        for(Fragmento f : fragmentos){
	          Servidor destino = null;  
	          for(Servidor s : this.servidores)
	            if(s.temCapacidade(f) && 
	              ((destino== null)|| (destino != null && destino.getLatenciaEscrita() > s.getLatenciaEscrita())))
	               destino = s;
	          if(destino == null)
	        	  throw new FragmentoNaoArmazenadoException(f.getId());
	          tempo += destino.gravar(f); 
	        }
        }catch(FragmentoNaoArmazenadoException exception){
	    	this.liberar(arquivo);
	    	throw new ArquivoNaoArmazenadoException(arquivo.getId(), exception);
	    }
        this.addArquivo(arquivo);
        return tempo;
    }  
    
    
    private void liberar(Arquivo arquivo) {
        Fragmento[] fragmentos = arquivo.getOrdenadoPorTamanho();
        for(Fragmento f : fragmentos){
        	if(f.getServidor() != null)
        		f.getServidor().liberar(f);
        }
	}

	public long getCapacidadeServidor(String id) throws BuscavelNaoEncontradoException{
        Buscador buscador = new Buscador();
        Servidor s = (Servidor) buscador.buscar(this.servidores, id);
        return s.getCapacidade();
    }    
    
    public double getTempoLeitura(String id) throws FragmentoNaoArmazenadoException, 
    												ArquivoNaoArmazenadoException{
        Buscador buscador = new Buscador();
        Arquivo a;
		try {
			a = (Arquivo) buscador.buscar(this.arquivos, id);
		} catch (BuscavelNaoEncontradoException e) {
			throw new ArquivoNaoArmazenadoException(id, e);
		}
        return a.getTempoRecuperacao();
    }      
    
    private void addArquivo(Arquivo arquivo){
        Arquivo[] novo = new Arquivo[this.arquivos.length + 1];
        for(int iCont = 0; iCont < this.arquivos.length; iCont++)
          novo[iCont] = this.arquivos[iCont];
        novo[novo.length - 1] = arquivo;
        this.arquivos = novo;
    }  
    
    public void addServidor(Servidor servidor){
        Servidor[] novo = new Servidor[this.servidores.length + 1];
        for(int iCont = 0; iCont < this.servidores.length; iCont++)
          novo[iCont] = this.servidores[iCont];
        novo[novo.length - 1] = servidor;
        this.servidores = novo;
    }  
    
    public String toString(){
        String str = "Servidores\n";
        for(Servidor s : this.servidores)
          str += s.toString() + "\n";
        str += "Arquivos\n";
        for(Arquivo a : this.arquivos)
          str += a.getDescritor() + "\n";
        
        return str + "\n"; 
        
    }    
    
}
