//tale thread ha il compito, saltuariamente, di effettuare un update dei master "noti", 
//richiedendo la lista al Name Server via UDP



import java.net.*;
import java.util.*;
import java.io.*;

public class UpdateListaMaster extends Thread{
	private int myPort=0;
	private DatagramSocket ds=null;

	
	
	public UpdateListaMaster(){
		super();
	}//constr


	public UpdateListaMaster(int arg_porta){
		super();
		myPort=arg_porta;
	}//constr

	
	public void run(){
				//inizializzo socket x refresh lista master
				try{
					if (myPort==0)
						ds = new DatagramSocket();
					else
						ds = new DatagramSocket(myPort);
					ds.setSoTimeout(Constants.attesaRec);
				}
				catch(Exception e){
					System.out.println("UpdateListaMaster-errore creazione socket UDP");
					return;
				}
				//ciclo infinito di refresh 
				while (true){
						Constants.prn("Thread che aggiorna lista master: vado in dns");
						this.aggiorna();
						try{
							Thread.sleep(ConstantsS.refreshListaMaster);
						}catch(Exception e){}
				}
	}//run
	
	
	public static void main(String[] args){
		UpdateListaMaster ulm = new UpdateListaMaster(10005);
		ulm.start();
	}
	
	synchronized private void aggiorna(){
				Vector listaIP = new Vector(10);
				byte[] buffer = new byte[65507];
					
				try{
					
					String richiesta = ConstantsS.ambito;
					byte[] data = richiesta.getBytes();
					InetAddress dest =  InetAddress.getByName(Constants.nsIP);
					
					
					DatagramPacket output = new DatagramPacket(data, data.length, dest, Constants.nsPort);
					DatagramPacket  input = new DatagramPacket(buffer, buffer.length);
					ds.send(output);
					// a questo punto ho mandato la richiesta al NS, devo prendere il risultato!!
					ds.receive(input);//se non risponde dopo AttesaNS msec catch eccezione
					String s = new String(input.getData(), 0, input.getLength());
					LineNumberReader lnr = new LineNumberReader(new StringReader(s));
					String inStr;
					int i=0;
					//Constants.prn("------lista DNS------");
					while ((inStr = lnr.readLine())!= null){
						listaIP.add(inStr);
						//Constants.prn(listaIP.elementAt(i++) + " " + i);
					}
					//Constants.prn("-fine lista DNS------");
				}
				catch (SocketException se){
				//gestione errore creazione socket
				Constants.prn("errore creazione socket UDP");
				return ;
				}
				catch (UnknownHostException uhe){
				//gestione errore NS non trovato
				Constants.prn("errore connessione host Name Server");
				return ;
				}
				catch (IOException ioe){
				//gestione errore scrittura su socket
				Constants.prn("errore IO su socket UDP host Name Server");
				return ;
				}// fine blocco catch

				if (listaIP.elementAt(0).toString().indexOf("ambito sbagliato")>=0) {
					Constants.prn("richiesta impossibile da soddisfare, nessun IP abilitato a tale ambito");
					return ;
				}


				
				Vector listaIpOld = this.getMasterFile();

				//listaIP=lista nuova, listaIpOld: vecchia
				//memorizzo in file

				
				
				PrintWriter dest;
				File filezRisultato;
				
				try{
					filezRisultato = new File("tempMaster.dat");
					dest = new PrintWriter(new BufferedWriter(new FileWriter(filezRisultato)));
				}
				catch(Exception e){
					System.out.println("errore");
					return ;
				}
				
				int notPresent=0;//num master che erano in lista e non lo sono piu'
				String temp[] = new String[listaIpOld.size()];
				int k=0;
				for (Enumeration e = listaIpOld.elements() ; e.hasMoreElements() ;) {
					String e2 = (String)e.nextElement();
					temp[k++]=e2;
				}
					
					
				for (int i=0; i<temp.length;i++){
					//System.out.println();
					String e2 = temp[i];
					//Constants.prn("considero elemento: " + e2);
					if (listaIP.contains(e2)){
						dest.println(e2);
						//System.out.println("scrivo master: " + e2);
						listaIP.remove(e2);
						listaIpOld.remove(e2);
					}
					else
						notPresent++;
				}
				//a tal punto nel file ho i master che sono ancora vivi, e li ho tolti dai due vector-->
				//nel vector listaIpOld non ho piu' nulla, nel listaIP (dal nameserver) ho quelli "nuovi"
				//ne scelgo un numero notPresent a caso, in modo da mantenere costante il numero di master contattati dallo slave!!!
				System.out.println("il num di master morti è: "+ notPresent);
				
				
				if (listaIP.size() > 0){//se avanzano dei master nella lista fornita dl ns
					Random r = new Random();
					for (int i=0; i < notPresent;i++){
								int ind = r.nextInt(listaIP.size());
								dest.println(listaIP.elementAt(ind));
								System.out.println("considero nuovo master in lista: " + listaIP.elementAt(ind));
								listaIP.remove(ind);
					}//for
				}
				dest.close();
				File f = new File("listaMaster.txt");

				f.delete();
				filezRisultato.renameTo(f);
	}//aggiorna
	
	
	
	
  private Vector getMasterFile(){
   			Vector temp=new Vector();
   			String[] temp2;
   			try {
					FileReader fis = new FileReader("listaMaster.txt");
					BufferedReader inp = new BufferedReader(fis);
					int i=0;
					String line;
					while ((line = inp.readLine())!=null){
						temp.addElement(line);
						i++;
					}
					//System.out.println("updateListaMaster - fine input");
					fis.close();
					return temp;
			} 
		
			catch ( Exception e){
				return null;
			}

   }//getMasterFile;
}//class