/* $Id: WebDavViewTableFactory.java 349 2011-09-11 15:02:16Z ohura $ */
package webdav;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Stack;

import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;

import org.apache.webdav.lib.Lock;

import smart_gs.GSConstants;
import webdav.table.PropFindModel;
import webdav.table.PropFindRenderer;
import webdav.table.PropFindSort;


public class WebDavViewTableFactory {
	
    private final PropFindModel model = new PropFindModel();
//    private final TableSorter sorter = new TableSorter(model);
    private final JTable table;
    protected WebDavProcessor webDavProcessor;
    protected WebDavDownLoadEvent webDavDownLoadEvent;
    protected WebDavUploadLoadEvent webDavUploadLoadEvent;
    protected Stack<String> stack = new Stack<String>();
    protected String owner = "user";
    protected JTextField filenameField;
    protected int mode;
    protected String lockToken;
    
    public static final int INITIALIZE    = 0;
    public static final int DOWNLOAD_DONE = 100;
    public static final int UPLOAD_DONE   = 200;
    
    
    protected int event = INITIALIZE;
    public WebDavViewTableFactory(int mode_,PropFindInfo[] propFindInfos,Color backgroundColor){
    	mode = mode_;
    	// table  = new JTable(sorter);
        table  = new JTable(model);
        // sorter.setTableHeader(table.getTableHeader());
        //table  = new JTable(model);
        //table.setAutoCreateRowSorter(true);

        table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                return super.getTableCellRendererComponent(table, value, false, false, row, column);
            }
        });
        //table.setRowSelectionAllowed(true);
        //table.setCellSelectionEnabled(true);
        table.setIntercellSpacing(new Dimension());
        //table.setRowMargin(0);
        table.setShowGrid(false);
        //table.setShowHorizontalLines(false);
        //table.setShowVerticalLines(false);


        TableColumn col = table.getColumnModel().getColumn(0);
        col.setMinWidth(0);
        col.setMaxWidth(0);
        col.setResizable(false);
        //table.removeColumn(col);
        col = table.getColumnModel().getColumn(1);
        col.setCellRenderer(new PropFindRenderer(table));
        col.setPreferredWidth(100);
        col = table.getColumnModel().getColumn(2);
        col.setPreferredWidth(300);
        
        InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        KeyStroke tab    = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
        KeyStroke enter  = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
        KeyStroke stab   = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK);
        KeyStroke senter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK);
        im.put(tab, im.get(enter));
        im.put(stab, im.get(senter));

        if(propFindInfos != null){
	        for(int i=0;i<propFindInfos.length;i++){
	            model.addPropFindList(propFindInfos[i]);
	        }
        }
        final Color orgColor = table.getSelectionBackground();
//        final Color tflColor = this.getBackground();
        final Color tflColor = backgroundColor;
        table.addFocusListener(new FocusListener() {
            public void focusGained(FocusEvent e) {
                table.setSelectionForeground(Color.WHITE);
                table.setSelectionBackground(orgColor);
            }
            public void focusLost(FocusEvent e) {
                table.setSelectionForeground(Color.BLACK);
                table.setSelectionBackground(tflColor);
            }
        });
        table.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent me) {
            	Point pt = me.getPoint();
               	int row = table.rowAtPoint(pt);
                String name = (String)model.getValueAt(row, 1);
                String size = (String)model.getValueAt(row, 3);
                if(me.getClickCount()==2) {
                	/*
                    int row = sorter.modelIndex(table.rowAtPoint(pt));
                    */
                    if(size.equals("")){
                    	model.clear();
                    	try{
                    		boolean upflg = false;
                            if(name.equals("..")){
                            	stack.pop();
//                            	stack.remove(0);
//                            	System.out.println("POP:" + stack.pop());
                            	name = "";
                            	upflg = true;
                            }
	                		String path_ = (String)stack.peek();
	                		if(path_ == null){
	                			path_ = "";
	                		}
	                		if(!path_.equals("")){
	                			if(!path_.equals("/")){
	                				if(!path_.endsWith("/")){
	                					path_+="/";
	                				}
	                			}else{
	                				path_ = "";
	                			}
	                			if(path_.startsWith("/")){
	                				path_ = path_.substring(1,path_.length());
	                			}
	                		}
	        				PropFindInfo[] propFindInfoChild = webDavProcessor.getPropFindInfo(path_ + name, 1);
        					if(!(stack.size() == 1 && upflg)){
	        					PropFindInfo propFindInfo = new PropFindInfo();
	        					propFindInfo.setDisplayname("..");
	        					propFindInfo.setDirectory(true);
	        					model.addPropFindList(propFindInfo);
        					}
	        				if(propFindInfoChild != null){
	        					propFindInfoChild = new PropFindSort().sort(propFindInfoChild);
	        					for(int i=0;i<propFindInfoChild.length;i++){
	        						model.addPropFindList(propFindInfoChild[i]);
	        					}
	        				}
	        				if(!upflg){
	        					stack.push(path_ + name);
	        				}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}else{
                        String path = (String)stack.peek();
                        if(mode == 0){
                            download(path,name);
                        }else{
                    		filenameField.setText(name);
                        }
					}
                }else{
                    if(mode == 1){
                        if(!size.equals("")){
	                    	if(filenameField != null){
	                    		filenameField.setText(name);
	                    	}
                        }
                    }
                }
            }
        });
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
                if(mode != 1){
                	return;
                }
                if(e.getValueIsAdjusting()){
                	return;
                }
                int row = table.getSelectedRow();
				if(row == -1){
					return;
				}
				String name = (String)model.getValueAt(row, 1);
				String size = (String)model.getValueAt(row, 3);
                if(!size.equals("")){
                	if(filenameField != null){
                		filenameField.setText(name);
                  	}
                 }
			}
        });
        stack.push("");
    }
    public boolean download(String path,String name){
		try {
			boolean unlock = true;
            PropFindInfo[] propFindInfoChild = webDavProcessor.getPropFindInfo(path,name, 0);
            ArrayList lockList = propFindInfoChild[0].getLocks();
            boolean readonly = false;
            if(lockList.size() != 0){
            	boolean lockcheck = true;
            	if(lockToken != null){
                	for(int i=0;i<lockList.size();i++){
                		Lock lock = (Lock)lockList.get(i);
                		String lockTokenTemp = lock.getLockToken();
                		if(lockTokenTemp != null){
                			if(lockToken.equals(lockTokenTemp)){
                				lockcheck = false;
                				break;
                			}
                		}
                	}
            	}
            	if(lockcheck){
            		readonly = true;
            	}else{
            		webDavProcessor.unlock(path, name, lockToken);
            		unlock = false;
            	}
            }
            if(JOptionPane.showConfirmDialog(
					new JFrame() , "Do you download it?"
				) != JOptionPane.YES_OPTION){
            	return false;
            }
            
            String lockTokenTemp = null;
/*            if(!readonly){
            	lockTokenTemp = webDavProcessor.lock(path,name,owner);
            }
*/
            if(!webDavProcessor.download(path,name,GSConstants.TEMP_PATH)){
				JOptionPane.showMessageDialog(
						new JFrame() , "Download failure" , "error" ,
						JOptionPane.ERROR_MESSAGE
					);
				return false;
			}
			if(webDavDownLoadEvent != null){
				webDavDownLoadEvent.setDownload(GSConstants.TEMP_PATH + name,lockTokenTemp);
				webDavDownLoadEvent.setDownloadpath(path);
				webDavDownLoadEvent.setDownloaname(name);
				webDavDownLoadEvent.setStack(stack);
				webDavDownLoadEvent.setUnlock(unlock);
				webDavDownLoadEvent.setReadonly(readonly);
			}
			return true;
		} catch (IOException e1) {
			JOptionPane.showMessageDialog(
					new JFrame() , "Download failure" , "error" ,
					JOptionPane.ERROR_MESSAGE
				);
			return true;
		}
    }
    
    public boolean downlaod(){
    	int row = table.getSelectedRow();
    	if(row == -1){
    		return false;
    	}
    	String path = (String)stack.peek();
    	String name = (String)model.getValueAt(row, 1);
    	String size = (String)model.getValueAt(row, 3);
    	if(size.equals("")){
    		return false;
    	}
    	return download(path,name);
    	
    }
    public boolean upload(){
    	if(webDavUploadLoadEvent == null){
    		return true;
    	}
    	boolean unlock = true;
    	String path = (String)stack.peek();
    	try {
	    	if(filenameField == null){
	    		return true;
	    	}
	    	String name = filenameField.getText();
	    	boolean lockcheck = true;
	    	if(filenameField != null){
	    		String oldname = webDavUploadLoadEvent.getUploadname();
	    		if(oldname == null){
	    			oldname = "";
	    		}
        		if(oldname.equals(name)){
        			if(webDavUploadLoadEvent.isReadonly()){
                    	JOptionPane.showMessageDialog(
        						new JFrame() , "This file is locked. " , "locked" ,
        						JOptionPane.ERROR_MESSAGE
        					);
        				return false;
        			}
                    PropFindInfo[] propFindInfoChild = webDavProcessor.getPropFindInfo(path,name, 0);
                    if(propFindInfoChild != null){
	                    ArrayList lockList = propFindInfoChild[0].getLocks();
	                    if(lockList.size() != 0){
	                    	if(lockToken != null){
		                    	for(int i=0;i<lockList.size();i++){
		                    		Lock lock = (Lock)lockList.get(i);
		                    		String lockTokenTemp = lock.getLockToken();
		                    		if(lockTokenTemp != null){
		                    			if(lockToken.equals(lockTokenTemp)){
		                    				lockcheck = false;
		                    				break;
		                    			}
		                    		}
		                    	}
	                    	}
	                    	if(lockcheck){
		                    	JOptionPane.showMessageDialog(
		        						new JFrame() , "This file is locked. " , "locked" ,
		        						JOptionPane.ERROR_MESSAGE
		        					);
		        				return false;
	                    	}
		        			unlock = false;
	                    }
	                    int input = JOptionPane.showConfirmDialog(new JFrame(),"Do you overwrite?");
	        			if (input != JOptionPane.OK_OPTION) {
	        				return false;
	        			}
                    }
        		}
        	}
	    	if(name.equals("")){
				JOptionPane.showMessageDialog(
						new JFrame() , "Please input the file name." , "error" ,
						JOptionPane.ERROR_MESSAGE
					);
	    		return false;
	    	}
    		File file = webDavUploadLoadEvent.getUploadfile();
    		String uploadlockToken = null;
    		if(!lockcheck){
    			uploadlockToken = lockToken;
    		}
		    if(!webDavProcessor.upload(path,name,file,uploadlockToken)){
		    	JOptionPane.showMessageDialog(
		    			new JFrame() , "Upload failure" , "error" ,
							JOptionPane.ERROR_MESSAGE
				);
				return false;
			}
/*            String lockTokenTemp = null;
            if(uploadlockToken == null){
            	lockTokenTemp = webDavProcessor.lock(path,name,owner);
	            if(lockTokenTemp == null){
					JOptionPane.showMessageDialog(
							new JFrame() , "It failed in the lock." , "locked" ,
							JOptionPane.ERROR_MESSAGE
						);
					return false;
	            }
	            lockToken = lockTokenTemp; 
            } */
			if(webDavDownLoadEvent != null){
				webDavDownLoadEvent.setDownload(GSConstants.TEMP_PATH + name,lockToken);
				webDavDownLoadEvent.setDownloadpath(path);
				webDavDownLoadEvent.setDownloaname(name);
				webDavDownLoadEvent.setStack(stack);
				webDavDownLoadEvent.setUnlock(unlock);
				webDavDownLoadEvent.setReadonly(false);
			}
    	} catch (IOException e1) {
    		e1.printStackTrace();
			JOptionPane.showMessageDialog(
					new JFrame() , "Upload failure" , "error" ,
					JOptionPane.ERROR_MESSAGE
				);
			return false;
		}
		return true;
	}
    public void unlock(){
    	 int row = table.getSelectedRow();
    	 if(row == -1){
    		 return;
    	 }
     	 String name = (String)model.getValueAt(row, 1);
     	 String size = (String)model.getValueAt(row, 3);
         if(!size.equals("")){
        	try{
		    	String path = (String)stack.peek();
	            PropFindInfo[] propFindInfoChild = webDavProcessor.getPropFindInfo(path,name, 0);
	            ArrayList lockList = propFindInfoChild[0].getLocks();
	            if(lockList.size() == 0){
					JOptionPane.showMessageDialog(
							new JFrame() , "This file is not locked. " , "locked" ,
							JOptionPane.ERROR_MESSAGE
						);
					return;
	            }
	            Lock lock = (Lock)lockList.get(0);
	            webDavProcessor.unlock(path,name,lock.getLockToken());
//	            webDavProcessor.unlock(path,name,"");
	            // リロード.
	            model.clear();
				propFindInfoChild = webDavProcessor.getPropFindInfo(path, 1);
				if(propFindInfoChild != null){
					if(stack.size() != 1){
						PropFindInfo propFindInfo = new PropFindInfo();
						propFindInfo.setDisplayname("..");
						propFindInfo.setDirectory(true);
						model.addPropFindList(propFindInfo);
					}
					propFindInfoChild = new PropFindSort().sort(propFindInfoChild);
					for(int i=0;i<propFindInfoChild.length;i++){
						model.addPropFindList(propFindInfoChild[i]);
					}
				}
				if(webDavUploadLoadEvent != null) {
					webDavUploadLoadEvent.setReadonly(false);
				}
        	} catch (IOException e1) {
				JOptionPane.showMessageDialog(
						new JFrame() , "Unlock failure" , "error" ,
						JOptionPane.ERROR_MESSAGE
					);
			}
        }
    }

    public void lock(){
   	 int row = table.getSelectedRow();
	 if(row == -1){
		 return;
	 }
 	 String name = (String)model.getValueAt(row, 1);
 	 String size = (String)model.getValueAt(row, 3);
     if(!size.equals("")){
    	try{
	    	String path = (String)stack.peek();
            PropFindInfo[] propFindInfoChild = webDavProcessor.getPropFindInfo(path,name, 0);
            ArrayList lockList = propFindInfoChild[0].getLocks();
            if(lockList.size() != 0){
				JOptionPane.showMessageDialog(
						new JFrame() , "This file is locked. " , "locked" ,
						JOptionPane.ERROR_MESSAGE
					);
				return;
            }
            String lockTokenTemp = webDavProcessor.lock(path,name,owner);
            if(lockTokenTemp == null){
				JOptionPane.showMessageDialog(
						new JFrame() , "It failed in the lock." , "locked" ,
						JOptionPane.ERROR_MESSAGE
					);
				return;
            }
            if(webDavDownLoadEvent != null){
				webDavDownLoadEvent.setLockToken(lockTokenTemp);
			}
            // リロード.
            model.clear();
			propFindInfoChild = webDavProcessor.getPropFindInfo(path, 1);
			if(propFindInfoChild != null){
				if(stack.size() != 1){
					PropFindInfo propFindInfo = new PropFindInfo();
					propFindInfo.setDisplayname("..");
					propFindInfo.setDirectory(true);
					model.addPropFindList(propFindInfo);
				}
				propFindInfoChild = new PropFindSort().sort(propFindInfoChild);
				for(int i=0;i<propFindInfoChild.length;i++){
					model.addPropFindList(propFindInfoChild[i]);
				}
			}
			webDavDownLoadEvent.setUnlock(false);
			webDavDownLoadEvent.setReadonly(true);
    	} catch (IOException e1) {
			JOptionPane.showMessageDialog(
					new JFrame() , "Lock failure" , "error" ,
					JOptionPane.ERROR_MESSAGE
				);
		}
    }
    
    }
    
    public void setWebDavProcessor(WebDavProcessor webDavProcessor){
    	this.webDavProcessor = webDavProcessor;
    }
    
    public JTable getJTable(){
    	return table;
    }
    
    public void setWebDavDownLoadEvent(WebDavDownLoadEvent webDavDownLoadEvent){
    	this.webDavDownLoadEvent = webDavDownLoadEvent;
    }
    public void seWebDavUploadLoadEvent(WebDavUploadLoadEvent webDavUploadLoadEvent){
    	this.webDavUploadLoadEvent = webDavUploadLoadEvent;
    }
	public String getOwner() {
		return owner;
	}
	public void setOwner(String owner) {
		this.owner = owner;
	}
	public JTextField getFilenameField() {
		return filenameField;
	}
	public void setFilenameField(JTextField filenameField) {
		this.filenameField = filenameField;
	}
	public void setLockToken(String lockToken) {
		this.lockToken = lockToken;
	}
	
	public void setStack(Stack<String> stack){
		this.stack = stack;
	}
    
/*    public static JTable getJtable(PropFindInfo[] propFindInfos,MouseAdapter mouseAdapter,Color backgroundColor){
    	WebDavViewTableFactory test = new WebDavViewTableFactory(propFindInfos,mouseAdapter,backgroundColor);
    	return test.getTable();
    } */
}
