package client;

import java.io.*;
import java.net.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;


public class Client extends JFrame implements Serializable{
        
    JButton      connectBut = new JButton("Connect");
           
            
    JTextField      ipText  = new JTextField("127.0.0.1");
    JPanel  connectionPanel = new JPanel(new FlowLayout()),
            mPanel          = new JPanel(new BorderLayout()),
            dListPanel      = new JPanel(new BorderLayout());
            
    List        filesList   = new List();
    JScrollPane fListScroll = new JScrollPane(filesList);
    JComboBox   dList       = new JComboBox();
    JLabel      detailsLab  = new JLabel("Not connected");
    
    Socket             sock;
    ObjectOutputStream oos;
    ObjectInputStream  ois;
    
    JButton downloadFile = new JButton("Download");
    
    MenuItem  downloadItem = new MenuItem("Download");
    PopupMenu popup =new PopupMenu();
    
  
    
    String requestedFile = "";
    JFileChooser fch =new JFileChooser("..\\");
    
    Thread recieveFileThread;
    
    ActionListener downloadAction = new ActionListener(){
           public void actionPerformed(ActionEvent e){
           	  fch.setDialogTitle("Where do you want to save the recieved file..!");
           	  int result = fch.showSaveDialog(mPanel);
           	  if(result == fch.APPROVE_OPTION){
           	  	send("GetFile#"+filesList.getSelectedItem());
           	  	JOptionPane.showMessageDialog(null,fch.getSelectedFile().getPath());
           	    requestedFile = !fch.getSelectedFile().getName().equals("") ? fch.getSelectedFile().getPath() : getAbsluteName(filesList.getSelectedItem());
           	  }
           	  
           }	
    };
    
    Runnable recieveMethod = new Runnable(){
    	public void run(){
    		int fileSize = 6022386;
    		long byteRead;
    		int  current;
    	
    		
    		
    		
    		try{
    			String hostAddress = sock.getInetAddress().getHostAddress();
    			Socket fileSock = new Socket(hostAddress,7117);
    			ObjectOutputStream oos= new ObjectOutputStream(fileSock.getOutputStream());
    			
    			byte[] byteArray = new byte[fileSize];
    			InputStream is = fileSock.getInputStream();
    			
    			
    			FileOutputStream fos = new FileOutputStream(requestedFile);
    			BufferedOutputStream bos = new BufferedOutputStream(fos);
    			
    			current = is.read(byteArray,0,byteArray.length);
    			
    			do{
    				byteRead = is.read(byteArray,current,(byteArray.length-current));
    				if(byteRead >= 0) current += byteRead;
    			}
    		    while(byteRead > -1);
    			
    			 bos.write(byteArray, 0 , current);
			     bos.flush();
			     bos.close();
			     sock.close();
    			
    		}
    		catch(Exception ex){
    			JOptionPane.showMessageDialog(null,ex.getMessage());
    		}
    	}
    };
    
    MouseAdapter filesListActions = new MouseAdapter(){
    public void mouseClicked(MouseEvent e){
	    if(e.getClickCount()==2){
		    send("GetFiles#"+filesList.getSelectedItem());
	    }
	    else if(e.getButton() == e.BUTTON3 || e.getButton() == e.BUTTON2_DOWN_MASK){
	    	popup.show(filesList,50,50);
	    }
    }	
    };
    
    Thread    recieveThread = new Thread(new Runnable(){
    	public void run(){

    	String cmd[],data,list[];
    	
    	while(true){
	    	try{
		    	cmd = ((String) ois.readObject()).split("#");
		    	if(cmd[0].equals("Drives")){
		    		
			    	list = cmd[1].split("@_@");
			    	refreshDrivesList(list);
	    	    }
	    	    else if(cmd[0].equals("Files")){
			    	list = cmd[1].split("@_@");
			    	refreshFilesList(list);
	    	    }
	    	    else if(cmd[0].equals("RecieveFile")){
	    	        recieveFileThread = new Thread(recieveMethod);
	    	        recieveFileThread.start();
	    	    }
	    	    else if(cmd[0].equals("Msg")){
	    	        JOptionPane.showMessageDialog(null,cmd[1]);
	    	    }
	    	}
	    	catch(StringIndexOutOfBoundsException ex)
	    	{
	    		JOptionPane.showMessageDialog(null,ex.getMessage());
	    	}
	    	catch(IOException ex){
	    		try{
	    			recieveThread.stop();
	    			ois.close();
	    			oos.close();
	    			sock.close();
	    			System.gc();
	    			
	    		}
	    		catch(Exception e){
	    			JOptionPane.showMessageDialog(null,"Cannot close the socket");
	    		}
	    		
	    	}
	    	catch(Exception ex){
	    	JOptionPane.showMessageDialog(null,"Error occured while recieving data from server : \n"+ex.getMessage());
	    	
	    	}
    	
    	}	
    	}
    });
    
    
    public Client() {
    super("Remote File Browser");
    setLayout(new BorderLayout());
    connectBut.addActionListener(new ActionListener(){
    	public void actionPerformed(ActionEvent e){
    	    		try{
	    	    		sock = new Socket(ipText.getText(),0x13FB);
	    	    	
	    	    		
	    	    		oos  = new ObjectOutputStream(sock.getOutputStream());
	    	    		ois  = new ObjectInputStream(sock.getInputStream());
	    	    	
	    	    		connectBut.setEnabled(false);
	    	    		ipText.setEnabled(false);
	    	    		
	    	    	    detailsLab.setText("Connected");
	    	    		
	    	    		recieveThread.start();
	    	    		
	    	    		send("GetDrives#");
	    	    		send("GetFiles#c:\\");
	    	    		
    	    		
    	    	    }
	    	    	catch(Exception ex){
	    	    	    JOptionPane.showMessageDialog(null,"Connection Failed for the following reason : \n"+ex.getMessage());
	    	    	}
    	    	
    	}
    });
    
    dList.addItemListener(new ItemListener(){
    	public void itemStateChanged(ItemEvent e){
    		send("GetFiles#"+dList.getSelectedItem());
    	}
    });
    
    
    
    filesList.addItemListener(new ItemListener(){
     	public void itemStateChanged(ItemEvent e){
     		
     		String temp=filesList.getSelectedItem();
     		if(temp.indexOf(".") < 0 || temp.indexOf(".") > temp.length()){
     			detailsLab.setText("Item type : Directory");
     		}
     		else if(!temp.substring(temp.lastIndexOf("."),temp.length()).equals("") && !temp.equals("\\..")){
     			detailsLab.setText("Item type : File");
     		}
     		else if(temp.equals("\\..")){
     			detailsLab.setText("Back..");
     		}
     		
     		else{
     			detailsLab.setText("" + filesList.countItems() + " Item(s) found");
     		}
     		
     	}
     	});
    
    downloadItem.addActionListener(downloadAction);
    popup.add(downloadItem);
    filesList.add(popup);
    popup.setEnabled(true);
    popup.setShortcut(new MenuShortcut(13,true));
    
    filesList.addMouseListener(filesListActions);
    filesList.addMouseMotionListener(filesListActions);
    
    mPanel.add(fListScroll,BorderLayout.CENTER);
    mPanel.add(dList,BorderLayout.SOUTH);
    
    
    
    
    connectionPanel.add(ipText);
    connectionPanel.add(connectBut);
    
    
    getContentPane().add(connectionPanel,BorderLayout.NORTH);
    getContentPane().add(mPanel,BorderLayout.CENTER);
    getContentPane().add(detailsLab,BorderLayout.SOUTH);
    	
    setDefaultCloseOperation(3);
    setSize(400,400);
    filesList.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
    this.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
    show();
    }
    
    private void refreshFilesList(String[] list){
    if(!list.equals(null)){
     filesList.removeAll();
     
     Font f = new Font(Font.SANS_SERIF,Font.BOLD,12);
     filesList.setFont(f);
     
     filesList.add("\\..");
     
     	
     for(int i=0;i<list.length;i++){
     	
     	filesList.add(list[i]);
     
     }
     detailsLab.setText("" + filesList.countItems() + " Item(s) found");
    }
    }
    
    private void refreshDrivesList(String[] list){
    if(!list.equals(null)){
     dList.removeAllItems();
     for(int i=0;i<list.length;i++){
     	dList.addItem(list[i]);
     }
    }
    }
    
    public void send(Object ob){
	    try{
		    oos.writeObject(ob);
		    oos.flush();
		    oos.reset();
	    }
	    catch(Exception ex){
	    	
	    }
    }
    
    public String getAbsluteName(String st){
    	return st.substring(st.lastIndexOf("\\")+1,st.length());
    }
    
    public static void main(String[] args)throws Exception {
      JFrame.setDefaultLookAndFeelDecorated(true);
      
      Client client = new Client();
      
    //  UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
   //   SwingUtilities.updateComponentTreeUI(client);
}}