package org.codehaus.plexus.archiver;

import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.archiver.zip.ZipFile;
import org.codehaus.plexus.archiver.zip.ZipEntry;
import org.codehaus.plexus.archiver.tar.TarInputStream;
import org.codehaus.plexus.util.FileUtils;

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.Enumeration;

/**
 * @author Erik Engstrom
 */
public class DuplicateFilesTest extends PlexusTestCase
{
    private static final File file1 = getTestFile("src/test/resources/group-writable/foo.txt");
    private static final File file2 = getTestFile("src/test/resources/world-writable/foo.txt");
    private static final File destination = getTestFile("target/output/duplicateFiles");

    public void testZipArchiver()
            throws Exception {
        File archive = createArchive("zip");

        ZipFile zf = new ZipFile(archive);
        Enumeration e = zf.getEntries();
        int entryCount = 0;
        while (e.hasMoreElements())
        {
            ZipEntry entry = (ZipEntry) e.nextElement();
            System.out.println(entry.getName());
            entryCount++;
        }
        //Zip file should have 2 entries, 1 for the directory and one for foo.txt
        assertEquals(2, entryCount);
        testArchive(archive, "zip");
    }

    public void testDirArchiver()
           throws Exception
    {
        createArchive("dir");
        testFinalFile("target/output/duplicateFiles.dir/duplicateFiles/foo.txt");
    }

    public void testTarArchiver()
            throws Exception
    {
        File archive = createArchive("tar");
        TarInputStream tis;

        tis = new TarInputStream(new BufferedInputStream(
                new FileInputStream(archive)));
        int entryCount = 0;
        while ((tis.getNextEntry()) != null) {
            entryCount++;
        }
        assertEquals(1, entryCount);
        testArchive(archive, "tar");
    }

    private File createArchive(String role)
            throws Exception
    {
        Archiver archiver = (Archiver) lookup(Archiver.ROLE, role);

        archiver.addFile(file1, "duplicateFiles/foo.txt");
        archiver.addFile(file2, "duplicateFiles/foo.txt");


        // delete it if it exists to ensure it is actually empty
        if (destination.exists())
        {
            destination.delete();
        }

        File archive = getTestFile("target/output/duplicateFiles." + role);
        if (archive.exists())
        {
            if (archive.isDirectory())
            {
                FileUtils.deleteDirectory(archive);
            } else
            {
                archive.delete();
            }
        }

        archiver.setDestFile(archive);
        archiver.createArchive();
        return archive;
    }

    private void testArchive(File archive, String role) throws Exception
    {
         // Check the content of the archive by extracting it

        UnArchiver unArchiver = (UnArchiver) lookup(UnArchiver.ROLE, role);
        unArchiver.setSourceFile(archive);

        unArchiver.setDestDirectory(getTestFile("target/output/"));
        unArchiver.extract();

        assertTrue(destination.exists());
        assertTrue(destination.isDirectory());
        testFinalFile("target/output/duplicateFiles/foo.txt");
    }

    private void testFinalFile(String path) throws Exception
    {
        File outputFile = getTestFile(path);
        assertTrue(outputFile.exists());
        BufferedReader reader = new BufferedReader(new FileReader(outputFile));
        String firstLine = reader.readLine();
        reader.close();
        reader = new BufferedReader(new FileReader(file2));
        String expectedFirstLine = reader.readLine();
        reader.close();
        assertEquals(expectedFirstLine, firstLine);
    }
}

