/*
 * @(#)ConnectEnterpriseParser.java
 *
 * Copyright (c) 2003 JSCAPE
 * 1147 S. 53rd Pl., Mesa, Arizona, 85206, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JSCAPE. ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with
 * the terms of the license agreement you entered into with JSCAPE.
 */
package com.jscape.inet.ftp;

import java.io.BufferedReader;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * Parser responsible for handling FTP directory listing returned in UNIX format.
 * The following is a partial example listing of the format expected.
 * <p/>
 * <pre>
 *  -ARTE-----TCP A cbeodm   22159   629629 Aug 06 05:47 PSEUDOFILENAME
 *  -ARTE-----TCP A cbeodm    4915  1031030 Aug 06 09:12 PSEUDOFILENAME
 *  -ARTE-----TCP A cbeodm   16941   321321 Aug 06 12:41 PSEUDOFILENAME
 *  -ARTE-----TCP A cbeodm    7872  3010007 Aug 07 02:31 PSEUDOFILENAME
 *  -ARTE-----TCP A cbeodm    2737   564564 Aug 07 05:54 PSEUDOFILENAME
 *  -ARTE-----TCP A cbeodm   14879   991991 Aug 07 08:57 PSEUDOFILENAME
 * </pre>
 */
public class ConnectEnterpriseParser
        implements FtpFileParser {

    /**
     * Parses directory listing.
     * Reads directory listing from FTP server and parses contents into an Enumeration of FtpFile.
     *
     * @return an Enumeration of FtpFile
     *
     * @throws IOException
     * @see FtpFile
     * @see Ftp#getDirListing
     */
    @SuppressWarnings("unchecked")
    public Enumeration parse(BufferedReader stream)
            throws IOException {
        Vector files = new Vector();

        String line = "";

        while ((line = stream.readLine()) != null) {
            FtpFile file = parseLine(line);

            if (!(file == null)) {
                files.add(file);
            }
        }
        return files.elements();
    }

    /**
     * Gets the date and time for an FtpFile entry sourced from a UNIX directory listing.
     *
     * @param file   the FtpFile
     * @param zone   the TimeZone to use when calculating time. Your default timezone is used if not provided.
     * @param locale the Locale to use when parsing date. Locale.US is used if not provided.
     *
     * @return a Date, or null if FtpFile#getDate or FtpFile#getTime values are null
     *
     * @throws ParseException if an error occurs while parsing entry
     * @see java.util.TimeZone
     * @see java.util.Locale
     * @see FtpFile
     */
    public Date getDateTime(FtpFile file, TimeZone zone, Locale locale)
            throws ParseException {
        Date d = null;
        SimpleDateFormat df = null;

        try {

            // set locale
            if (locale != null) {
                df = new SimpleDateFormat("MMM dd HH:mm", locale);
            } else {
                df = new SimpleDateFormat("MMM dd HH:mm", Locale.US);
            }

            // set timezone
            if (zone != null) {
                df.setTimeZone(zone);
            }

            d = df.parse(file.getDate() + " " + file.getTime());
            Calendar cal = new GregorianCalendar();
            int currentYear = cal.get(GregorianCalendar.YEAR);
            cal.setTime(d);
            cal.set(GregorianCalendar.YEAR, currentYear);
            d = cal.getTime();
        } catch (ParseException e) {
            if (locale != null) {
                df = new SimpleDateFormat("MMM dd yyyy HH:mm", locale);
                d = df.parse(file.getDate() + " " + file.getTime());
            } else {
                df = new SimpleDateFormat("MMM dd yyyy HH:mm", Locale.US);
                d = df.parse(file.getDate() + " " + file.getTime());
            }
        }
        return d;
    }

    /**
     * Gets the date and time for an FtpFile entry sourced from a UNIX directory listing.
     *
     * @param file the FtpFile
     *
     * @throws ParseException if an error occurs while parsing entry
     * @see FtpFile
     */
    public Date getDateTime(FtpFile file)
            throws ParseException {
        return this.getDateTime(file, null, null);
    }


    private FtpFile parseLine(String line) {
        //Connect:Enterprise Style
        //"-C--E-----FTP B BCC3I1       7670  1294495 Jan 13 07:42 ConEnt file",
        //"-C--E-----FTS B BCC3I1       7670  1294495 Jan 13 07:42 ConEnt file2",
        //"-AR--M----TCP B ceunix      17570  2313708 Mar 29 08:56 ALL_SHORT1.zip",

        StringTokenizer tokens = new StringTokenizer(line);
        int tokenCount = tokens.countTokens();

        if (tokenCount < 7) {
            return (FtpFile) null;
        }

        FtpFile file = new FtpFile("", line, this);

        file.setPermission(tokens.nextToken());
        tokens.nextToken();
        file.setOwner(tokens.nextToken());
        file.setGroup(tokens.nextToken());
        file.setFilesize(tokens.nextToken());
        file.setDate(tokens.nextToken() + " " + tokens.nextToken());

        String isTime = tokens.nextToken();

        if (isTime.indexOf(":") == -1) {
            file.setTime("00:00");
        } else {
            file.setTime(isTime);
        }

        StringBuffer filename = new StringBuffer();
        while (tokens.hasMoreTokens()) {
            filename.append(tokens.nextToken());
            if (tokens.hasMoreTokens()) {
                filename.append(" ");
            }
        }

        file.setFilename(filename.toString());

        return file;
    }

    /**
     * Parses a string which contains a date and returns a date object
     *
     * @param date The string will be parsed
     *
     * @return A object date which corresponds with the input string argument
     *
     * @throws ParseException if an error ocurrs
     */
    public Date getFileDate(String date)
            throws ParseException {
        // Format spected Aug 06
        Date fileDate = null;
        try {
            SimpleDateFormat format = new SimpleDateFormat("MMM d", Locale.US);
            fileDate = format.parse(date);
            Calendar fileCalendar = Calendar.getInstance();
            fileCalendar.setTime(fileDate);
            Calendar calendar = Calendar.getInstance();
            int year = calendar.get(Calendar.YEAR);
            fileCalendar.set(Calendar.YEAR, year);
            fileDate = fileCalendar.getTime();
        } catch (ParseException e) {
            // todo: ignore?
        }
        return fileDate;
    }
}
