package Server;

import java.io.*;
import java.net.*;
import javax.swing.*;
import java.util.jar.*;


public class Server  {
 
  
 private ServerSocket server;
 private ObjectInputStream ois;
 private ObjectOutputStream oos;
 private Socket client;
 private File f,lastDrivesList[],drivesListBuffer[];
 private String temp,cmd[],list="";
 private static Server serverApp;
 private int lastCount=0;
 protected String requestedFile ="";
 
  Thread serverThread     = new Thread(new Runnable(){
  	public void run(){
	  
	  	
	  	  try
		  {
		    server = new ServerSocket(5115);
		    client = server.accept();
		    oos = new ObjectOutputStream(client.getOutputStream());
		    ois = new ObjectInputStream(client.getInputStream());
		    
		   
		  }
		    
		  catch(Exception ex){
		    //JOptionPane.showMessageDialog(null,"Cannot open port for the following reason :\n"+ex.getMessage())	;
		  }
	  	
	  	while(true){
	  	try {
	  	cmd =((String) ois.readObject()).split("#");
	  	
	  	if(cmd[0].equals("GetFiles")){

			  	list="";
			  	
				    f = new File((!cmd[1].equals("\\..") ? cmd[1] :
				    	         (!isRoot(f.getName()) ? f.getParent() : f.getName() )));
					    if(f.isDirectory()){
					    	
						    for(int i=0;i<f.list().length;i++)
						    {
						    	list +=f.getPath()+"\\"+ f.list()[i] + (i < f.list().length ? "@_@" :"");
						    }

						    send("Files#"+list.substring(0,list.length()));
						    temp = cmd[1];
					    }
					  
		    }
		  else if(cmd[0].equals("GetDrives")){
				  		try {
				   
					    drivesListBuffer = File.listRoots();
					    
					    for(int i=0;i<drivesListBuffer.length;i++){
					    	if(drivesListBuffer[i].canRead()){
					    		list += drivesListBuffer[i].getPath() + ( i < drivesListBuffer.length ? "@_@" : "");
					    	}
						    
					    }
					    
					    send("Drives#"+list.substring(0,list.length()-3));
					   
				        }
					    catch (Exception ex) {
					    	
							    send("Msg#Cannot access this file..!\nMessage : " + ex.getMessage());
						}
		
				  	updateDrivesList.start();
				  }
		  else if(cmd[0].equals("GetFile")){
		  	requestedFile  = cmd[1];
		  	sendFileThread = new Thread(sendFileThreadMethod);
		  	sendFileThread.start();
		  }
		  
		}
	    catch(IOException ex){
	   	     startListening();
	   }
	   catch (Exception ex) {
		   send("Msg#cannot open this file or directory for the following reason :\n"+ex.getMessage());
	   }
	   
	  }	
	 }
});
  
  
  Thread sendFileThread;
  
  Runnable sendFileThreadMethod =new Runnable(){
  	public void run(){
  		File reqFile = null;
  		ServerSocket file_Transfer_Socket = null;
  		byte[] byteArray = new byte[(int)reqFile.length()];
  	    Socket       fileReciever = null;
  	    ObjectInputStream  ois    = null;
  	    BufferedInputStream bis   = null;
  	    OutputStream        os    = null;
  	
  		try {
  		   reqFile = new File(requestedFile);
  		   
  		     
           file_Transfer_Socket = new ServerSocket(7117);
           
           send("RecieveFile#"+reqFile.length());
           
           fileReciever = file_Transfer_Socket.accept();
           ois = new ObjectInputStream(fileReciever.getInputStream());
           bis = new BufferedInputStream(ois);
           os  = fileReciever.getOutputStream();
           
           bis.read(byteArray,0,byteArray.length);
           os.write(byteArray,0,byteArray.length);
           
           send("Msg#Transfer completed!");
           
           os.close();
           bis.close();
           ois.close();
           fileReciever.close();
           file_Transfer_Socket.close();
           
           
		}
		catch (Exception ex) {
		   send("Msg#Transfer cannot be completed \n"+ex.getMessage());
		   try{
		      if(os!=null){
		       os.close();
	           bis.close();
	           ois.close();
	           fileReciever.close();
	           file_Transfer_Socket.close();
		      }
			   
		   }
		   catch(Exception eex){
		   	
		   }
          
		}
	  	}
  };
  
	Thread updateDrivesList = new Thread(new Runnable(){
	  	public void run(){
	  		String listDrives ="";
	  	
		  	
	  		while(true){
	  			
	  			
	  			if(drivesListBuffer.length != File.listRoots().length)
	  			{
	  				listDrives="";
	  				drivesListBuffer = File.listRoots();
	  				
	  				for(int i=0;i<drivesListBuffer.length;i++){
				    	if(drivesListBuffer[i].canRead()){
				    		listDrives += drivesListBuffer[i].getPath() + ( i < drivesListBuffer.length ? "@_@" : "");
				    	}
				    
				    }
				    send("Drives#"+listDrives.substring(0,listDrives.length()-3));
	  			}
	  			try{
	  				updateDrivesList.sleep(1000);
	  			}
	  			catch(Exception ex){
	  				
	  			}
	  		}
	  	}
	  });

/*
//  Thread updateDrivesList = new Thread(new Runnable(){
//  	public void run(){
//  		String listDrives ="";
//
//  		while(true){
//  			if(lastCount < getReadAbleDrives(File.listRoots()).length)
//  			{
//  				drivesListBuffer = getReadAbleDrives(File.listRoots());
//  				
//  				listDrives="";
//  
//  				for(int i=0;i<drivesListBuffer.length;i++){
//			    		listDrives += drivesListBuffer[i].getPath() + ( i < drivesListBuffer.length ? "@_@" : "");
//			    	}
//
//			    send("Drives#"+listDrives.substring(0,listDrives.length()-3));
//  			}
//  			try{
//  				updateDrivesList.sleep(1000);
//  			}
//  			catch(Exception ex){
//  				JOptionPane.showMessageDialog(null,ex.getMessage());
//  				}
//  			}
//  		}
//  	}
//  );*/

/*
 *
//    private class ClientsThread extends Thread{
//    	
//    	public ClientsThread(){
//    		super((Runnable)this);
//    	}
//    	
//    	public ClientsThread(Runnable target){
//    		super(target);
//    	}
//    	
//    	public void run(){
//    		
//    	}
//    }*/
  
   private File[] getReadAbleDrives(File[] f){
   	 int count=0;
//   	 for(int i=0;i<f.length;i++){
//   	 	if(f[i].canRead() && !f[i].getName().equals(drivesListBuffer[i].getName())){
//   	 		count++;
//   	 		drivesListBuffer[i] = f[i];
//   	 	}
   	 	File[] temp = new File[f.length];
   	 	for(int i=0;i<f.length;i++)
   	 		if(f[i].canRead()){
   	 		temp[count++] = f[i];	
   	 		}
   	 	return temp;
   	 
  
   }
   
    public Server() {
  
    serverThread.start();
    
    }
    
    public static void main(String[] args) {
    serverApp = new Server();
    }
    
    public boolean isRoot(String name){
    	File[] list = File.listRoots();
    	for(int i=0;i<list.length;i++)
    		if(list[i].getName().equals(name))
    			return true;
    	return false; 
    }
    
    public void send(Object ob){
	    try{
		    oos.writeObject(ob);
		    oos.flush();
		    oos.reset();
	    }
	    catch(Exception ex){
	    	
	    }
    }
    
    private void startListening(){
    	try
   	    {
    	ois.close();
		oos.close();
		client.close();
		server.close();
		serverThread = null;
		updateDrivesList = null;

		serverApp = null;
		System.gc();
		serverApp = new Server();
		}
   	    catch(Exception e){
   	    	JOptionPane.showMessageDialog(null,"Cannot close sockets :\n"+e.getMessage());
   	    	System.exit(1);
   	    }
    }
}
