/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.xmlbeans.impl.tool;

import org.apache.xmlbeans.SystemProperties;
import org.apache.xmlbeans.impl.schema.SchemaTypeSystemImpl;

import java.io.*;
import java.util.List;
import java.util.Arrays;
import java.util.Comparator;
import java.util.ArrayList;
import java.util.jar.JarFile;
import java.util.Enumeration;
import java.util.zip.ZipEntry;

public class Diff
{
    public static void main(String[] args)
    {
        if (args.length != 2)
        {
            System.out.println("Usage: diff <jarname1> <jarname2> to compare two jars");
            System.out.println("  or   diff <dirname1> <dirname2> to compare two dirs");
            return;
        }
        File file1 = new File(args[0]);
        if (!file1.exists())
        {
            System.out.println("File \"" + args[0] + "\" not found.");
            return;
        }
        File file2 = new File(args[1]);
        if (!file2.exists())
        {
            System.out.println("File \"" + args[1] + "\" not found.");
            return;
        }
        List result = new ArrayList();
        if (file1.isDirectory())
        {
            if (!file2.isDirectory())
            {
                System.out.println("Both parameters have to be directories if the first parameter is a directory.");
                return;
            }
            dirsAsTypeSystems(file1, file2, result);
        }
        else
        {
            if (file2.isDirectory())
            {
                System.out.println("Both parameters have to be jar files if the first parameter is a jar file.");
                return;
            }
            try
            {
            JarFile jar1 = new JarFile(file1);
            JarFile jar2 = new JarFile(file2);
            jarsAsTypeSystems(jar1, jar2, result);
            }
            catch (IOException ioe)
            { ioe.printStackTrace(); }
        }
        if (result.size() < 1)
            System.out.println("No differences encountered.");
        else
        {
            System.out.println("Differences:");
            for (int i = 0; i < result.size(); i++)
                System.out.println(result.get(i).toString());
        }
    }

    /**
     * Diffs the contents of two jars, looking only at the schema typesystems
     * saved inside those jars
     */
    public static void jarsAsTypeSystems(JarFile jar1, JarFile jar2, List diffs)
    {
        Enumeration entries1 = jar1.entries();
        Enumeration entries2 = jar2.entries();
        List list1 = new ArrayList();
        List list2 = new ArrayList();
        for (; entries1.hasMoreElements(); )
        {
            ZipEntry ze = (ZipEntry) entries1.nextElement();
            String name = ze.getName();
            if (name.startsWith(SchemaTypeSystemImpl.METADATA_PACKAGE_GEN + "/system/s") && name.endsWith(".xsb"))
                list1.add(ze);
        }
        for (; entries2.hasMoreElements(); )
        {
            ZipEntry ze = (ZipEntry) entries2.nextElement();
            String name = ze.getName();
            if (name.startsWith(SchemaTypeSystemImpl.METADATA_PACKAGE_GEN + "/system/s") && name.endsWith(".xsb"))
                list2.add(ze);
        }
        ZipEntry[] files1 = (ZipEntry[]) list1.toArray(new ZipEntry[list1.size()]);
        ZipEntry[] files2 = (ZipEntry[]) list2.toArray(new ZipEntry[list2.size()]);
        ZipEntryNameComparator comparator = new ZipEntryNameComparator();
        Arrays.sort(files1, comparator);
        Arrays.sort(files2, comparator);
        int i1 = 0;
        int i2 = 0;
        while (i1 < files1.length && i2 < files2.length)
        {
            String name1 = files1[i1].getName();
            String name2 = files2[i2].getName();
            int dif = name1.compareTo(name2);
            if (dif == 0)
            {
                // Compare the files
                zipEntriesAsXsb(files1[i1], jar1, files2[i2], jar2, diffs);
                i1++; i2++; // Move to next pair
            }
            else if (dif < 0)
            {
                // dir1 contains a file that dir2 doesn't
                diffs.add("Jar \"" + jar1.getName() + "\" contains an extra file: \"" +
                    name1 + "\"");
                i1++;
            }
            else if (dif > 0)
            {
                // dir2 contains a file that dir1 doesn't
                diffs.add("Jar \"" + jar2.getName() + "\" contains an extra file: \"" +
                    name2 + "\"");
                i2++;
            }
        }
        while (i1 < files1.length)
        {
            diffs.add("Jar \"" + jar1.getName() + "\" contains an extra file: \"" +
                files1[i1].getName() + "\"");
            i1++;
        }
        while (i2 < files2.length)
        {
            diffs.add("Jar \"" + jar2.getName() + "\" contains an extra file: \"" +
                files2[i2].getName() + "\"");
            i2++;
        }
    }

    /**
     * Diffs the contents of two dirs looking only at the xsb files
     * contained in these two dirs
     * Updated diffs with a list of differences (for the time being, strings
     * describing the difference)
     */
    public static void dirsAsTypeSystems(File dir1, File dir2, List diffs)
    {
        assert dir1.isDirectory() : "Parameters must be directories";
        assert dir2.isDirectory() : "Parameters must be directories";

        /**
         * Navigate three directories deep to get to the type system.
         * Assume the schema[METADATA_PACKAGE_LOAD]/system/* structure
         */
        File temp1 = new File(dir1, SchemaTypeSystemImpl.METADATA_PACKAGE_GEN + "/system");
        File temp2 = new File(dir2, SchemaTypeSystemImpl.METADATA_PACKAGE_GEN + "/system");
        if (temp1.exists() && temp2.exists())
        {
            File[] files1 = temp1.listFiles();
            File[] files2 = temp2.listFiles();
            if (files1.length == 1 && files2.length == 1)
            {
                temp1 = files1[0];
                temp2 = files2[0];
            }
            else
            {
                if (files1.length == 0)
                    temp1 = null;
                if (files2.length == 0)
                    temp2 = null;
                if (files1.length > 1)
                {
                    diffs.add("More than one typesystem found in dir \"" +
                        dir1.getName() + "\"");
                    return;
                }
                if (files2.length > 1)
                {
                    diffs.add("More than one typesystem found in dir \"" +
                        dir2.getName() + "\"");
                    return;
                }                    
            }
        }
        else
        {
            if (!temp1.exists())
                temp1 = null;
            if (!temp2.exists())
                temp2 = null;
        }
        if (temp1 == null && temp2 == null)
            return;
        else if (temp1 == null || temp2 == null)
        {
            if (temp1 == null)
                diffs.add("No typesystems found in dir \"" + dir1 + "\"");
            if (temp2 == null)
                diffs.add("No typesystems found in dir \"" + dir2 + "\"");
            return;
        }
        else
        {
            dir1 = temp1;
            dir2 = temp2;
        }

        boolean diffIndex = isDiffIndex();
        XsbFilenameFilter xsbName = new XsbFilenameFilter();
        File[] files1 = dir1.listFiles(xsbName);
        File[] files2 = dir2.listFiles(xsbName);
        FileNameComparator comparator = new FileNameComparator();
        Arrays.sort(files1, comparator);
        Arrays.sort(files2, comparator);
        int i1 = 0;
        int i2 = 0;
        while (i1 < files1.length && i2 < files2.length)
        {
            String name1 = files1[i1].getName();
            String name2 = files2[i2].getName();
            int dif = name1.compareTo(name2);
            if (dif == 0)
            {
                if (diffIndex || !files1[i1].getName().equals("index.xsb"))
                    filesAsXsb(files1[i1], files2[i2], diffs); // Compare the files
                i1++; i2++; // Move to next pair
            }
            else if (dif < 0)
            {
                // dir1 contains a file that dir2 doesn't
                diffs.add("Dir \"" + dir1.getName() + "\" contains an extra file: \"" +
                    name1 + "\"");
                i1++;
            }
            else if (dif > 0)
            {
                // dir2 contains a file that dir1 doesn't
                diffs.add("Dir \"" + dir2.getName() + "\" contains an extra file: \"" +
                    name2 + "\"");
                i2++;
            }
        }
        while (i1 < files1.length)
        {
            diffs.add("Dir \"" + dir1.getName() + "\" contains an extra file: \"" +
                files1[i1].getName() + "\"");
            i1++;
        }
        while (i2 < files2.length)
        {
            diffs.add("Dir \"" + dir2.getName() + "\" contains an extra file: \"" +
                files2[i2].getName() + "\"");
            i2++;
        }
    }

    private static boolean isDiffIndex()
    {
        String prop = SystemProperties.getProperty("xmlbeans.diff.diffIndex");
        if (prop == null)
            return true;
        if ("0".equals(prop) || "false".equalsIgnoreCase(prop))
            return false;
        return true;
    }

    /**
     * Diffs the two given files assuming they are in xsb format
     * Updates diffs with differences in string format
     */
    public static void filesAsXsb(File file1, File file2, List diffs)
    {
        assert file1.exists() : "File \"" + file1.getAbsolutePath() + "\" does not exist.";
        assert file2.exists() : "File \"" + file2.getAbsolutePath() + "\" does not exist.";
        try
        {
        FileInputStream stream1 = new FileInputStream(file1);
        FileInputStream stream2 = new FileInputStream(file2);
        streamsAsXsb(stream1, file1.getName(), stream2, file2.getName(), diffs);
        }
        catch (FileNotFoundException fnfe)
        { }
        catch (IOException ioe)
        { }
    }

    public static void zipEntriesAsXsb(ZipEntry file1, JarFile jar1,
        ZipEntry file2, JarFile jar2, List diffs)
    {
        try
        {
        InputStream stream1 = jar1.getInputStream(file1);
        InputStream stream2 = jar2.getInputStream(file2);
        streamsAsXsb(stream1, file1.getName(), stream2, file2.getName(), diffs);
        }
        catch (IOException ioe)
        { }
    }

    public static void streamsAsXsb(InputStream stream1, String name1,
        InputStream stream2, String name2, List diffs)
        throws IOException
    {
        ByteArrayOutputStream buf1 = new ByteArrayOutputStream();
        ByteArrayOutputStream buf2 = new ByteArrayOutputStream();
        XsbDumper.dump(stream1, "", new PrintStream(buf1));
        XsbDumper.dump(stream2, "", new PrintStream(buf2));
        stream1.close();
        stream2.close();
        readersAsText(new StringReader(buf1.toString()), name1,
            new StringReader(buf2.toString()), name2, diffs);
    }

    public static void readersAsText(Reader r1, String name1, Reader r2, String name2,
        List diffs)
        throws IOException
    {
        org.apache.xmlbeans.impl.util.Diff.readersAsText(r1, name1, r2, name2, diffs);
    }

    private static class XsbFilenameFilter implements FilenameFilter
    {
        public boolean accept(File dir, String name)
        {
            return name.endsWith(".xsb");
        }
    }

    private static class ZipEntryNameComparator implements Comparator
    {
        public boolean equals(Object object)
        {
            return this == object;
        }

        public int compare(Object object1, Object object2)
        {
            assert (object1 instanceof ZipEntry) : "Must pass in a java.util.zip.ZipEntry as argument";
            assert (object2 instanceof ZipEntry) : "Must pass in a java.util.zip.ZipEntry as argument";

            String name1 = ((ZipEntry) object1).getName();
            String name2 = ((ZipEntry) object2).getName();
            return name1.compareTo(name2);
        }
    }

    private static class FileNameComparator implements Comparator
    {
        public boolean equals(Object object)
        {
            return this == object;
        }

        public int compare(Object object1, Object object2)
        {
            assert (object1 instanceof File) : "Must pass in a java.io.File as argument";
            assert (object2 instanceof File) : "Must pass in a java.io.File as argument";

            String name1 = ((File) object1).getName();
            String name2 = ((File) object2).getName();
            return name1.compareTo(name2);
        }
    }
}
