/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.log4j.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;


public class Compare {
  static final int B1_NULL = -1;
  static final int B2_NULL = -2;

  private static final InputStream open(
          final Class<org.apache.log4j.rewrite.RewriteAppenderTest> testClass,
          final String fileName) throws IOException {
      String resourceName = fileName;
      if (fileName.startsWith("witness/")) {
          resourceName = fileName.substring(fileName.lastIndexOf('/') + 1);
      }
      InputStream is = testClass.getResourceAsStream(resourceName);
      if (is == null) {
          File file = new File(fileName);
          if (file.exists()) {
              is = new FileInputStream(file);
          } else {
              throw new FileNotFoundException("Resource "
                      + resourceName + " not found");
          }
      }
      return is;
  }

  public static boolean compare(Class<org.apache.log4j.rewrite.RewriteAppenderTest> testClass,
                                final String file1,
                                final String file2)
    throws IOException {
      try (BufferedReader in1 = new BufferedReader(new FileReader(file1));
           BufferedReader in2 = new BufferedReader(new InputStreamReader(
              open(testClass, file2)))) {
          return compare(testClass, file1, file2, in1, in2);
      }
  }
    
 public static boolean compare(
         Class<org.apache.log4j.rewrite.RewriteAppenderTest> testClass, String file1, String file2, BufferedReader in1, BufferedReader in2) throws IOException {

    String s1;
    int lineCounter = 0;

    while ((s1 = in1.readLine()) != null) {
      lineCounter++;

      String s2 = in2.readLine();

      if (!s1.equals(s2)) {
        System.out.println(
          "Files [" + file1 + "] and [" + file2 + "] differ on line "
          + lineCounter);
        System.out.println("One reads:  [" + s1 + "].");
        System.out.println("Other reads:[" + s2 + "].");
        outputFile(testClass, file1);
        outputFile(testClass, file2);

        return false;
      }
    }

    // the second file is longer
    if (in2.read() != -1) {
      System.out.println(
        "File [" + file2 + "] longer than file [" + file1 + "].");
      outputFile(testClass, file1);
      outputFile(testClass, file2);

      return false;
    }

    return true;
  }

  /** 
   * 
   * Prints file on the console.
   *
   */
  private static void outputFile(Class<org.apache.log4j.rewrite.RewriteAppenderTest> testClass, String file)
    throws IOException {
    InputStream is = open(testClass, file);
    BufferedReader in1 = new BufferedReader(new InputStreamReader(is));

    String s1;
    int lineCounter = 0;
    System.out.println("--------------------------------");
    System.out.println("Contents of " + file + ":");

    while ((s1 = in1.readLine()) != null) {
      lineCounter++;
      System.out.print(lineCounter);

      if (lineCounter < 10) {
        System.out.print("   : ");
      } else if (lineCounter < 100) {
        System.out.print("  : ");
      } else if (lineCounter < 1000) {
        System.out.print(" : ");
      } else {
        System.out.print(": ");
      }

      System.out.println(s1);
    }
    in1.close();
  }


    public static boolean gzCompare(final Class<org.apache.log4j.rewrite.RewriteAppenderTest> testClass,
                                    final String actual,
                                    final String expected)
      throws IOException {
      String resourceName = expected;
      int lastSlash = expected.lastIndexOf("/");
      if (lastSlash >= 0) {
          resourceName = expected.substring(lastSlash + 1);
      }
      InputStream resourceStream = testClass.getResourceAsStream(resourceName);
      if (resourceStream == null) {
          throw new FileNotFoundException("Could not locate resource " + resourceName);
      }

        try (BufferedReader in1 = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(actual))));
             BufferedReader in2 = new BufferedReader(new InputStreamReader(new GZIPInputStream(resourceStream)))) {
            return gzCompare(testClass, actual, expected, in1, in2);
        }
    }

    public static boolean gzCompare(Class<org.apache.log4j.rewrite.RewriteAppenderTest> testClass, String file1, String file2, BufferedReader in1, BufferedReader in2) throws IOException {

      String s1;
      int lineCounter = 0;

      while ((s1 = in1.readLine()) != null) {
        lineCounter++;

        String s2 = in2.readLine();

        if (!s1.equals(s2)) {
          System.out.println(
            "Files [" + file1 + "] and [" + file2 + "] differ on line "
            + lineCounter);
          System.out.println("One reads:  [" + s1 + "].");
          System.out.println("Other reads:[" + s2 + "].");
          outputFile(testClass, file1);
          outputFile(testClass, file2);

          return false;
        }
      }

      // the second file is longer
      if (in2.read() != -1) {
        System.out.println(
          "File [" + file2 + "] longer than file [" + file1 + "].");
        outputFile(testClass, file1);
        outputFile(testClass, file2);

        return false;
      }

      return true;
    }

}
