
/**
 * JMichelle (Java Midori Shell)
 * Copyright (C) 2000 Midori IGA 
 *   (http://www01.u-page.so-net.ne.jp/db3/midori/midosoft.html)
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package jp.ne.nifty.iga.midori.shell.dir;

import jp.ne.nifty.iga.midori.shell.MdShellDef;
import jp.ne.nifty.iga.midori.shell.eng.MdShellEnv;
import jp.ne.nifty.iga.midori.shell.io.*;
import java.io.*;
import java.text.*;
import java.util.*;

/**
 * JMichelle (Java Midori Shell) : path class
 */
public class MdShellDirDirectoryFtpClient
	extends MdShellDirDirectoryAbstract
{
	private String strUsername;
	private String strPassword;

	private boolean isStartDirectory=false;

	private MdShellEnv shellenv=null;

	public static final String DEFAULT_ENCODE="EUC_JP";
	public String strEncode=null;

	public MdShellDirDirectoryFtpClient(MdShellEnv shellenv,String strUri)
	{
		this.shellenv=shellenv;

		init();

		setType(FTP);

		MdShellFtpServerNode ftpservernode=(MdShellFtpServerNode)shellenv.getFtpServerList().get(SZ_PROTOCOL[getType()]+MdShellDirFactory.getHostName(strUri));
		strUsername=ftpservernode.strUser;
		strPassword=ftpservernode.strPassword;

		if(MdShellDirFactory.getDirectory(strUri,true).equals("/."))
		{
			isStartDirectory=true;
		}

		setName(strUri);
	}

	private void init()
	{
		try{
			"TEST".getBytes(DEFAULT_ENCODE);
			strEncode=DEFAULT_ENCODE;
		}catch(UnsupportedEncodingException ex){
			//System.out.println(ex.toString());
			//ex.printStackTrace();
		}
	}

	private boolean isOpened=false;
	private void ensureOpen()
	{
		if(isOpened)
		{
			return;
		}

		if(getName().endsWith("/."))
		{
			MdShellFtpc ftpc=MdShellFtpc.getInstance(shellenv,getName());
			if(ftpc!=null)
			{
				setName(getName().substring(0,getName().length()-2)+ftpc.pwd());
			}
		}

		setFileLength(0);
		lastModified=0;
		bCanWrite=true;
		bCanRead=true;

		isOpened=true;
	}

	public String getShortName()
	{
		//ensureOpen();

		if(isStartDirectory)
		{
			return MdShellDirFactory.getHostName(getName());
		}

		int iFind=getName().lastIndexOf('/');
		if(iFind>=0)
		{
			return getName().substring(getName().lastIndexOf('/')+1);
		}

		return getName();
	}

	public MdShellDirDirectoryAbstract getParentDirectory()
	{
		ensureOpen();

		String strSeparator="/";

		String strCurrentDirectory=getName();
		if(strCurrentDirectory.lastIndexOf('/')<=(SZ_PROTOCOL[getType()]).length())
		{
			return new MdShellDirDirectoryRoot();
		}

		strCurrentDirectory=strCurrentDirectory.substring(0,strCurrentDirectory.lastIndexOf('/'));
		//if(MdShellDef.IS_DEBUG)shellenv.getOut().println("trace: ftp.getParentDirectory()"+strCurrentDirectory);

		MdShellDirDirectoryFtpClient filesystemnode=new MdShellDirDirectoryFtpClient(shellenv,strCurrentDirectory);
		return filesystemnode;
	}

	public MdShellDirDirectoryAbstract getChildDirectory(String strSubDirectory)
	{
		ensureOpen();

		String strSeparator="/";

		//try{
			String strCurrentDirectory=getName();

			String strFullPathDirectory=null;
			if(strCurrentDirectory.endsWith(strSeparator))
			{
				strFullPathDirectory=strCurrentDirectory+strSubDirectory;
			}
			else
			{
				strFullPathDirectory=strCurrentDirectory+strSeparator+strSubDirectory;
			}

			MdShellDirDirectoryFtpClient filesystemnode=new MdShellDirDirectoryFtpClient(shellenv,strFullPathDirectory);

			//if(filesystemnode.isDirectoryExist())
			{
				return filesystemnode;
			}
		//return null;
	}

	// ???
	public boolean isDirectoryExist()
	{
		ensureOpen();

		return true;
	}

	/**
	 * @param int iDirectoryAndFile: 1:DIRECTORY&FILE 2:DIRECTORY 3:FILE
	 */
	public Vector listDirectory(MdShellEnv shellenv,int iSelect,String strRe)
	{
		ensureOpen();

		Vector vecList=new Vector(1024);

		MdShellFtpc ftpc=MdShellFtpc.getInstance(shellenv,getName());
		if(ftpc==null)
		{
			return vecList;
		}
		if(ftpc.cd(MdShellDirFactory.getDirectory(getName(),true))==false)
		{
			shellenv.getOut().println("change directory is failed: "+MdShellDirFactory.getDirectory(getName(),true));
			return vecList;
		}
		if(MdShellDef.IS_DEBUG)shellenv.getOut().println(ftpc.pwd());

		try{
			byte[] byteList=ftpc.ls();

			InputStreamReader inputstreamReader=null;
			if(strEncode==null)
			{
				inputstreamReader=new InputStreamReader(new ByteArrayInputStream(byteList));
			}
			else
			{
				inputstreamReader=new InputStreamReader(new ByteArrayInputStream(byteList),strEncode);
			}

			BufferedReader reader=new BufferedReader(inputstreamReader);

			for(;;)
			{
				String strRead=reader.readLine();
				if(strRead==null)
				{
					break;
				}

				String strSeparator="/";

				if(MdShellDef.IS_DEBUG)shellenv.getOut().println(strRead);
				if(strRead.length()>10)
				{
					FtpFileNodeInfo nodeInfo=buildFileNameFromLsResult(strRead);
					if(nodeInfo==null)
					{
						continue;
					}

					if(nodeInfo.strPermission.charAt(0)=='d')
					{
						if(nodeInfo.strFileName!=null
						&& (iSelect==SELECT_DIRECTORY_FILE
						|| iSelect==SELECT_DIRECTORY))
						{
							String strUri=getName();
							if(strUri.endsWith("/."))
							{
								strUri=strUri.substring(0,strUri.length()-2);
							}
							else if(strUri.endsWith("/"))
							{
								strUri=strUri.substring(0,strUri.length()-1);
							}

							MdShellDirDirectoryFtpClient look=new MdShellDirDirectoryFtpClient(shellenv,strUri+strSeparator+nodeInfo.strFileName);
							look.setFileLength(nodeInfo.lFileSize);
							look.lastModified=nodeInfo.lLastModified;

							if(isReMatch(strRe,look.getShortName()))
							{
								vecList.addElement(look);
							}
						}
					}
					else if(nodeInfo.strPermission.charAt(0)=='-')
					{
						if(nodeInfo.strFileName!=null
						&& (iSelect==SELECT_DIRECTORY_FILE
						|| iSelect==SELECT_FILE))
						{
							String strUri=getName();
							if(strUri.endsWith("/."))
							{
								strUri=strUri.substring(0,strUri.length()-2);
							}
							else if(strUri.endsWith("/"))
							{
								strUri=strUri.substring(0,strUri.length()-1);
							}

							MdShellDirFileFtpClient look=(MdShellDirFileFtpClient)MdShellDirFactory.getInstance(shellenv,strUri+strSeparator+nodeInfo.strFileName,false);
							look.setFileLength(nodeInfo.lFileSize);
							look.lastModified=nodeInfo.lLastModified;

							if(isReMatch(strRe,look.getShortName()))
							{
								vecList.addElement(look);
							}
						}
					}
				}
			}
		}catch(IOException ex){
			System.out.println(ex.toString());
			ex.printStackTrace();
		}

		Collections.sort(vecList,new MdShellFileNameComparator(getCollatorInstance()));

		return vecList;
	}

	private FtpFileNodeInfo buildFileNameFromLsResult(String strReadLine)
	{
		ensureOpen();

		StringTokenizer toknizerTab=new StringTokenizer(strReadLine," ",false);
		try{
			FtpFileNodeInfo nodeInfo=new FtpFileNodeInfo();

			nodeInfo.strPermission=toknizerTab.nextToken();

			if(nodeInfo.strPermission.startsWith("d")==false
			&& nodeInfo.strPermission.startsWith("-")==false)
			{
				nodeInfo.strPermission=toknizerTab.nextToken();
				if(nodeInfo.strPermission.startsWith("d")==false
				&& nodeInfo.strPermission.startsWith("-")==false)
				{
					//System.out.println("not directory nor file.");
					return null;
				}
			}

			Vector vecRead=new Vector();
			for(;;)
			{
				try{
					vecRead.addElement(toknizerTab.nextToken());
				}catch(NoSuchElementException ex){
					break;
				}
			}

			String strFileMonth=null;
			String strFileDate=null;
			String strFileTime=null;

			if(vecRead.size()==8)
			{
				nodeInfo.lFileSize=Integer.parseInt((String)vecRead.elementAt(3));

				strFileMonth=(String)vecRead.elementAt(4);
				strFileDate=(String)vecRead.elementAt(5);
				strFileTime=(String)vecRead.elementAt(6);
				nodeInfo.strFileName=(String)vecRead.elementAt(7);
			}
			else if(vecRead.size()==7)
			{
				nodeInfo.lFileSize=Integer.parseInt((String)vecRead.elementAt(2));

				strFileMonth=(String)vecRead.elementAt(3);
				strFileDate=(String)vecRead.elementAt(4);
				strFileTime=(String)vecRead.elementAt(5);
				nodeInfo.strFileName=(String)vecRead.elementAt(6);
			}
			else
			{
				shellenv.getOut().println("directory or file line ["+strReadLine+"] is ignored.");
				return null;
			}


			String strYear=""+Calendar.getInstance().get(Calendar.YEAR);

			{
				if(strFileTime.indexOf(':')<0)
				{
					strYear=strFileTime;
					strFileTime="00:00";
				}

				// month string to month
				String[] straryMonth={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
				for(int index=0;index<straryMonth.length;index++)
				{
					if(strFileMonth.equals(straryMonth[index]))
					{
						strFileMonth=""+(index+1);
					}
				}

				// for japaniese locale.
				strFileMonth=strFileMonth.replace('\u6708',' ').trim();
				strFileDate=strFileDate.replace('\u65e5',' ').trim();
				if(strYear.indexOf('\u5e74')>0)
				{
					strYear=strYear.replace('\u5e74',' ').trim();
				}

				String strDateTime=strYear+"/"+strFileMonth+"/"+strFileDate+" "+strFileTime;
				try{
					SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy/MM/dd HH:mm");
					// no good. DateFormat simpleDateFormat=DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
					Date timeCheck=simpleDateFormat.parse(strDateTime);
					nodeInfo.lLastModified=timeCheck.getTime();
				}catch(ParseException ex){
					if(MdShellDef.IS_DEBUG)shellenv.getOut().println("parse: ["+strDateTime+"] :"+ex.toString());
					//ex.printStackTrace();
				}
			}

			return nodeInfo;
		}catch(NoSuchElementException ex){
			// None.
		}
		return null;
	}

	public boolean delete()
	{
		return false;
	}
}

class FtpFileNodeInfo
{
	public String strPermission=null;
	public String strFileName=null;
	public long lFileSize=0;
	public long lLastModified=0;
}


