package net.argius.filetool;

import java.io.*;

/**
 * アーカイブファイル展開処理。
 */
public final class FileExpander {

    private Expander expander;

    /**
     * FileExpanderの生成。
     * @param src
     * @throws IOException
     */
    public FileExpander(File src) throws IOException {
        this(src, ArchiveType.getType(src));
    }

    /**
     * FileExpanderの生成。
     * @param src
     * @param type
     * @throws IOException
     */
    public FileExpander(File src, ArchiveType type) throws IOException {
        if (type == ArchiveType.TAR) {
            expander = new TarExpander(new FileInputStream(src));
        } else if (type == ArchiveType.TGZ) {
            expander = new TarExpander(new GzipDecompressor(new FileInputStream(src)));
        } else if (type == ArchiveType.TBZ) {
            expander = new TarExpander(new Bzip2Decompressor(new FileInputStream(src)));
        } else if (type == ArchiveType.ZIP) {
            expander = new ZipExpander(src);
        } else if (type == ArchiveType.LZH) {
            expander = new LhaExpander(new FileInputStream(src));
        } else {
            throw new IllegalStateException("ArchiverType: " + type);
        }
    }

    /**
     * @param dstdir
     * @throws IOException
     */
    public void expand(File dstdir) throws IOException {
        if (!dstdir.isDirectory()) {
            throw new IllegalArgumentException("not a directory: " + dstdir);
        }
        try {
            for (ArchiveEntry entry; (entry = expander.nextEntry()) != ArchiveEntry.EMPTY;) {
                if (entry.isDirectory()) {
                    continue;
                }
                File tmp = File.createTempFile("filetool-expand-", ".tmp");
                tmp.deleteOnExit();
                String name = entry.getName();
                OutputStream fos = new FileOutputStream(tmp);
                try {
                    expander.expand(fos);
                } finally {
                    fos.close();
                }
                File newfile = new File(dstdir, name);
                if (newfile.isDirectory()) {
                    continue;
                }
                IOUtilities.move(tmp, newfile, false);
                newfile.setLastModified(entry.getLastModified());
            }
        } finally {
            expander.close();
        }
    }

    /**
     * @throws IOException 
     */
    public void close() throws IOException {
        expander.close();
    }

    /**
     * 使い方の表示。
     */
    private static void printUsage() {
        PrintStream err = System.err;
        err.println("FileArchiver (argius-filetool)");
        err.println("usage : (command) src [dst]");
        err.println("options: none");
    }

    /**
     * FileExpanderの実行。
     * @param args パラメータ(see 'usage')
     */
    public static void main(String[] args) {
        if (args.length < 1) {
            printUsage();
            return;
        }
        for (int i = 0; i < args.length; i++) {
            String arg = args[i];
            if (arg.equals("-h") || arg.equals("--help")) {
                printUsage();
                return;
            }
        }
        final String commandNameInfo = "FileExpander: ";
        int status;
        try {
            File src = new File(args[0]);
            File dst = new File((args.length >= 2) ? args[1] : ".");
            FileExpander expander = new FileExpander(src);
            try {
                expander.expand(dst);
            } finally {
                expander.close();
            }
            status = 0;
        } catch (IOException ex) {
            System.out.println(commandNameInfo + ex.getMessage());
            status = 1;
        } catch (Exception ex) {
            String message = ex + Utilities.getFirstStackTrace(ex, DiskUsage.class);
            System.out.println(commandNameInfo + message);
            status = 255;
        }
        if (status > 0) {
            System.exit(status);
        }
    }

}
