/*
 * Created on 2005-01-25
 *
 * Part of the Symbian development plug-in for Eclipse
 * Copyright (C) Mikołaj Zalewski, 2005
 */
package pl.zalewski.mikolaj.symbdev.ui.internal.widgets;

import org.eclipse.cdt.ui.CElementLabelProvider;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ContainerSelectionDialog;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.model.WorkbenchContentProvider;

import pl.zalewski.mikolaj.symbdev.SymbdevPlugin;
import pl.zalewski.mikolaj.symbdev.SymbianSDKEntry;
import pl.zalewski.mikolaj.symbdev.utils.FileStringType;
import pl.zalewski.mikolaj.symbdev.utils.PathUtils;

/**
 * A dialog to choose a file from the Workspace, filesystem or
 * %EPOCROOT%
 * 
 * @author mikolaj
 */
public class DirectoryDialog extends Dialog {

    public DirectoryDialog(Shell parentShell, SymbianSDKEntry sdk, IPath localPath,
            boolean directory) {
        super(parentShell);
        fSDK=sdk;
        fDirectory=directory;
        fLocalPath=localPath;
    }
    
    public DirectoryDialog(Shell parentShell, SymbianSDKEntry sdk, IPath localPath)
    {
        this(parentShell, sdk, localPath, true);
    }
    
    static void setSpan(Control control, int num)
    {
        GridData gd=new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalSpan=num;
        control.setLayoutData(gd);
    }
    
    protected Control createDialogArea(Composite cmp)
    {   
        Composite panel=(Composite)super.createDialogArea(cmp);
        GridLayout layout=(GridLayout)panel.getLayout();
        layout.numColumns=3;
        
        Label l=new Label(panel, SWT.NONE);
        l.setText((fDirectory?"Select directory:":"Select file:"));
        setSpan(l, 3);
        
        fSel[0]=new Button(panel, SWT.RADIO);
        fSel[0].setText("From the Workspace:");
        setSpan(fSel[0], 3);
        
        l=new Label(panel, SWT.NONE);
        GridData gd=new GridData();
        gd.widthHint=100;
        l.setLayoutData(gd);
        fDirs[0]=new Text(panel, SWT.BORDER);
        gd=new GridData();
        gd.widthHint=300;
        fDirs[0].setLayoutData(gd);
        fDirs[0].addListener(SWT.Modify, new Listener() {
            public void handleEvent(org.eclipse.swt.widgets.Event e) {
                selectRadio(0);
            }			
        });
        Button b=new Button(panel, SWT.PUSH);
        b.setText("Change...");
        b.addListener(SWT.Selection, new Listener() {
            public void handleEvent(org.eclipse.swt.widgets.Event e) {
                workspaceDialog();
            }			
        });
        
        fSel[1]=new Button(panel, SWT.RADIO);
        fSel[1].setText("From the SDK:");
        setSpan(fSel[1], 3);
        
        l=new Label(panel, SWT.NONE);
        fDirs[1]=new Text(panel, SWT.BORDER);
        fDirs[1].addListener(SWT.Modify, new Listener() {
            public void handleEvent(org.eclipse.swt.widgets.Event e) {
                selectRadio(1);
            }			
        });
        setSpan(fDirs[1], 1);
        b=new Button(panel, SWT.PUSH);
        b.setText("Change...");
        b.addListener(SWT.Selection, new Listener() {
            public void handleEvent(org.eclipse.swt.widgets.Event e) {
                sdkPathDialog();
            }			
        });

        fSel[2]=new Button(panel, SWT.RADIO);
        fSel[2].setText("From the filesystem:");
        setSpan(fSel[2], 3);
        
        l=new Label(panel, SWT.NONE);
        fDirs[2]=new Text(panel, SWT.BORDER);
        fDirs[2].addListener(SWT.Modify, new Listener() {
            public void handleEvent(org.eclipse.swt.widgets.Event e) {
                selectRadio(2);
            }			
        });
        setSpan(fDirs[2], 1);
        b=new Button(panel, SWT.PUSH);
        b.setText("Change...");     
        b.addListener(SWT.Selection, new Listener() {
            public void handleEvent(org.eclipse.swt.widgets.Event e) {
                filesystemDialog();
            }			
        });
        
        setupResult();
        
        return panel;
    }
    
    public void setupResult()
    {
        if (fResult==null)
            return;
        
        FileStringType ft=new FileStringType(fResult, fSDK.epocRoot,
                fLocalPath.toString());
        switch (ft.fType)
        {
        	case FileStringType.PATH_WORKSPACE:
        	    selectRadio(0);
        		fDirs[0].setText(ft.fString);
        		break;
        	case FileStringType.PATH_ROOT:
        	    selectRadio(1);
        		fDirs[1].setText(ft.fString);
        		break;
        	case FileStringType.PATH_NOT_FOUND:
        	case FileStringType.PATH_FILESYSTEM:
        	    selectRadio(2);
        		fDirs[2].setText(ft.fString);
        		break;
        }

    }
    
    public void selectRadio(int i)
    {
        fSel[0].setSelection(i==0);
        fSel[1].setSelection(i==1);
        fSel[2].setSelection(i==2);
    }
    
    public boolean validatePath(String dir)
    {
  	    if (dir.indexOf(' ')!=-1)
  	    {
  	        MessageDialog.openError(getShell(), SymbdevPlugin.MESSAGE_TITLE,
  	        	"The "+(fDirectory?"directory":"file")+" name should " +
  	        	"not contain a space.");
  	        return false;      	              	        
  	    }
  	    return true;
    }
    
    public void workspaceDialog()
    {
        IPath cont;
        if (fDirectory)
        {
	        ContainerSelectionDialog dialog = 
	            new ContainerSelectionDialog(getShell(),
	                    ResourcesPlugin.getWorkspace().getRoot(),
	                    false, "Select directory");
	        if (dialog.open()!=Dialog.OK)
	        	return;
	        Object[] result=dialog.getResult();
	        if (result==null || result.length==0)
	            return;
	        cont=(IPath)result[0];
        } else
        {
/*            ResourceSelectionDialog dialog=new ResourceSelectionDialog(
                    getShell(), ResourcesPlugin.getWorkspace().getRoot(),
                    "Select file");*/
            
            ElementTreeSelectionDialog dialog=new ElementTreeSelectionDialog(
                    getShell(), new CElementLabelProvider(), new WorkbenchContentProvider());
            dialog.setInput(ResourcesPlugin.getWorkspace());
	        if (dialog.open()!=Dialog.OK)
	        	return;
	        Object[] result=dialog.getResult();            
	        if (result==null || result.length==0)
	            return;
	        if (!(result[0] instanceof IFile))
	        {
	            MessageDialog.openError(getShell(),
	                    SymbdevPlugin.MESSAGE_TITLE,
	                    "The selection is not a file");
	            return;
	        }
	        cont=((IFile)result[0]).getFullPath();
        }
        if (!validatePath(cont.toString()))
            return;
        fDirs[0].setText(cont.toString());
        selectRadio(0);
    }
    
    public void filesystemDialog()
    {
        String dir;
        if (fDirectory)
        {
	      	org.eclipse.swt.widgets.DirectoryDialog dlg=
	      	    new org.eclipse.swt.widgets.DirectoryDialog(getShell());
	      	dir=dlg.open();
        } else {
            FileDialog dlg=new FileDialog(getShell());
            dir=dlg.open();
        }
      	if (dir!=null)
      	{
      	    if (Character.toUpperCase(dir.charAt(0))!=
      	        Character.toUpperCase(fSDK.epocRoot.charAt(0)))
      	    {
      	        MessageDialog.openError(getShell(), SymbdevPlugin.MESSAGE_TITLE,
	                "The "+(fDirectory?"directory":"file")+" should be a on" +
	                		" the same drive as the SDK.");
      	        return;      	        
      	    }
      	    if (!validatePath(dir))
      	        return;
      	    fDirs[2].setText(dir);
            selectRadio(2);
      	}
    }
    
    public void sdkPathDialog()
    {
        String dir;
        if (fDirectory)
        {
	      	org.eclipse.swt.widgets.DirectoryDialog dlg=
	      	    new org.eclipse.swt.widgets.DirectoryDialog(getShell());
	      	dlg.setFilterPath(fSDK.epocRoot);
	      	dir=dlg.open();
        } else
        {
            FileDialog dlg=new FileDialog(getShell());
            dlg.setFilterPath(fSDK.epocRoot);
            dir=dlg.open();
        }
      	if (dir!=null)
      	{
      	    if (!dir.toUpperCase().startsWith(fSDK.epocRoot.toUpperCase()))
      	    {
      	        MessageDialog.openError(getShell(), SymbdevPlugin.MESSAGE_TITLE,
      	                "The "+(fDirectory?"directory":"file")+"should " +
      	                "be a subdirectory of the SDK root");
      	        return;
      	    }
      	    if (!validatePath(dir))
      	        return;
      	    dir=dir.substring(fSDK.epocRoot.length()-1); // leave '\'
      	    fDirs[1].setText(dir);
            selectRadio(1);
      	}
    }
    
    public boolean execute()
    {
        create();
        return open()==OK;
    }

    protected void okPressed() {
        Path sdkRoot=new Path(fSDK.epocRoot);
        IPath p=null;
        if (fSel[0].getSelection())
        {
            IResource f;
            if (fDirectory) f=ResourcesPlugin.getWorkspace().getRoot().
            	getFolder(new Path(fDirs[0].getText()));
            else f=ResourcesPlugin.getWorkspace().getRoot().
            	getFile(new Path(fDirs[0].getText()));
            if (!f.exists())
            {
                MessageDialog.openWarning(getShell(), SymbdevPlugin.MESSAGE_TITLE,
                        (fDirectory?"Directory not found":"File not found"));
                super.okPressed();
                return;
            }
            p=f.getLocation();
        } else if (fSel[1].getSelection())
        {
            p=sdkRoot.append(fDirs[1].getText());
        } else if (fSel[2].getSelection())
        {
            p=new Path(fLocalPath.getDevice(), fDirs[2].getText());
            if (!p.isAbsolute())
            {
                fResult=fDirs[2].getText();
                fResultPath=p;
                super.okPressed();
            	return;
            }
        }
        
        fResultPath=p;
        
        if (sdkRoot.isPrefixOf(p))
        {
            String[] segments=p.segments();
            StringBuffer b=new StringBuffer();
            for (int i=sdkRoot.segments().length; i<segments.length; i++)
            {
                b.append('\\');
                b.append(segments[i]);
            }
            fResult=b.toString();
        } else fResult=PathUtils.makeRelativePath(p, fLocalPath);
        super.okPressed();
    }
    
    public String getResult()
    {
        return fResult;
    }
    
    public IPath getResultPath() {
        return fResultPath;
    }
    
    public void setResult(String path)
    {
        fResult=path;
    }
    
    Text[] fDirs=new Text[3];
    Button[] fSel=new Button[3];
    SymbianSDKEntry fSDK;
    IPath fLocalPath;
    IPath fResultPath;
    boolean fDirectory;
    String fResult;
}
