/*
 * 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.geode.codeAnalysis;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.apache.geode.codeAnalysis.decode.CompiledClass;
import org.apache.geode.codeAnalysis.decode.CompiledField;
import org.apache.geode.codeAnalysis.decode.CompiledMethod;
import org.apache.geode.internal.serialization.Version;

public class CompiledClassUtils {

  static Set<String> allowedDataSerializerMethods;

  static {
    allowedDataSerializerMethods = new HashSet<>();
    Version.getAllVersions().iterator().forEachRemaining((version) -> {
      allowedDataSerializerMethods.add("toDataPre_" + version.getMethodSuffix());
      allowedDataSerializerMethods.add("fromDataPre_" + version.getMethodSuffix());
    });
  }

  /**
   * Parse the given class files and return a map of name->Dclass. Any IO exceptions are consumed by
   * this method and written to stderr.
   *
   * @return the parsed classes
   */
  public static Map<String, CompiledClass> parseClassFiles(List<File> classFiles) {
    Map<String, CompiledClass> result = new HashMap<String, CompiledClass>();

    for (File file : classFiles) {
      try {
        CompiledClass parsed = CompiledClass.getInstance(file);
        if (!parsed.isInterface()) {
          result.put(parsed.fullyQualifiedName(), parsed);
        }
      } catch (IOException e) {
        System.err.println("Exception while parsing " + file.getName() + ": " + e.getMessage());
      }
    }
    return result;
  }

  /**
   * Parse the files in the given jar file and return a map of name->CompiledClass. Any IO
   * exceptions are consumed by this method and written to stderr.
   *
   * @param jar the jar file holding classes
   */
  public static Map<String, CompiledClass> parseClassFilesInJar(File jar) {
    Map<String, CompiledClass> result = new HashMap<String, CompiledClass>();
    try {
      JarFile jarfile = new JarFile(jar);
      for (Enumeration<JarEntry> entries = jarfile.entries(); entries.hasMoreElements();) {
        JarEntry entry = entries.nextElement();
        if (entry.getName().endsWith(".class")) {
          try {
            CompiledClass parsed = CompiledClass.getInstance(jarfile.getInputStream(entry));
            if (!parsed.isInterface()) {
              result.put(parsed.fullyQualifiedName(), parsed);
            }
          } catch (IOException e) {
            System.err
                .println("Exception while parsing " + entry.getName() + ": " + e.getMessage());
          }
        }
      }
    } catch (IOException e) {
      System.err.println("Error opening jar file:");
      e.printStackTrace(System.err);
    }
    return result;
  }

  /**
   * Parse the files in the given jar file and return a map of name->CompiledClass. Any IO
   * exceptions are consumed by this method and written to stderr.
   */
  public static Map<String, CompiledClass> parseClassFilesInDir(File buildDir) {
    Map<String, CompiledClass> result = new HashMap<String, CompiledClass>();
    for (File entry : buildDir.listFiles()) {
      if (entry.isDirectory()) {
        result.putAll(parseClassFilesInDir(entry));
      } else if (entry.getName().endsWith(".class")) {
        try {
          CompiledClass parsed = CompiledClass.getInstance(new FileInputStream(entry));
          if (!parsed.isInterface()) {
            result.put(parsed.fullyQualifiedName(), parsed);
          }
        } catch (IOException e) {
          System.err.println("Exception while parsing " + entry.getName() + ": " + e.getMessage());
        }
      }
    }
    return result;
  }

  /**
   * returns a collection of all of the .class files in the given list of files and directories.
   *
   * @param filenames a list of the files and directories to examine
   * @param recursive whether to recurse into subdirectories
   * @return a sorted list of the .class files found
   */
  public static List<File> findClassFiles(String parentPath, String[] filenames,
      boolean recursive) {
    // Grab classes and Expand directory names found in list
    List<File> classFiles = new ArrayList<File>();
    for (int i = 0; i < filenames.length; i++) {
      File f = new File(parentPath + filenames[i]);
      String n = f.getAbsolutePath();
      if (!f.exists()) {
        System.err.println("File " + n + " does not exist - skipping");
        continue;
      }
      if (f.isFile() && f.getName().endsWith(".class")) {
        classFiles.add(f);
        continue;
      }
      if (f.isDirectory() && recursive) {
        classFiles.addAll(findClassFiles(f.getAbsolutePath() + "/", f.list(), true));
      }
    }
    Collections.sort(classFiles);
    return classFiles;
  }

  public static List<ClassAndMethodDetails> loadClassesAndMethods(File file) throws IOException {
    List<ClassAndMethodDetails> result = new LinkedList<ClassAndMethodDetails>();
    FileReader fr = new FileReader(file);
    LineNumberReader in = new LineNumberReader(fr);
    ClassAndMethodDetails cam;
    while ((cam = ClassAndMethodDetails.create(in)) != null) {
      result.add(cam);
    }
    fr.close();
    return result;
  }

  public static String diffSortedClassesAndMethods(List<ClassAndMethodDetails> goldRecord,
      List<ClassAndMethods> toDatas) throws IOException {

    StringBuilder newClassesSb = new StringBuilder(10000);
    StringBuilder changedClassesSb = new StringBuilder(10000);
    newClassesSb.append("New or moved classes----------------------------------------\n");
    int newBase = newClassesSb.length();
    changedClassesSb.append("Modified classes--------------------------------------------\n");
    int changedBase = changedClassesSb.length();

    Iterator<ClassAndMethods> it = toDatas.iterator();
    ClassAndMethods newclass = null;

    for (ClassAndMethodDetails gold : goldRecord) {
      if (newclass == null) {
        if (!it.hasNext()) {
          changedClassesSb.append(gold).append(": deleted or moved\n");
          continue;
        }
        newclass = it.next();
      }
      int comparison = -1;
      while (newclass != null
          && (comparison = gold.className.compareTo(newclass.dclass.fullyQualifiedName())) > 0) {
        newClassesSb.append(newclass).append("\n");
        if (it.hasNext()) {
          newclass = it.next();
        } else {
          newclass = null;
        }
      }
      if (comparison == 0) {
        ClassAndMethods nc = newclass;
        newclass = null;
        if (gold.methods.size() != nc.numMethods()) {
          changedClassesSb.append(nc).append(": method count (expected " + gold.methods.size()
              + " but found " + nc.numMethods() + ")\n");
          continue;
        }
        boolean comma = false;
        for (Map.Entry<String, CompiledMethod> entry : nc.methods.entrySet()) {
          CompiledMethod method = entry.getValue();
          String methodName = method.name();
          if (!methodName.equals("toData") && !methodName.equals("fromData")
              && !allowedDataSerializerMethods.contains(methodName)) {
            if (comma) {
              changedClassesSb.append(", and ");
            } else {
              changedClassesSb.append(nc).append(":  ");
              comma = true;
            }
            changedClassesSb.append(methodName)
                .append(" is not a valid method name - doesn't match any Version");
            continue;
          }
          Integer goldCode = gold.methods.get(methodName);
          if (goldCode == null) {
            if (comma) {
              changedClassesSb.append(", and ");
            } else {
              changedClassesSb.append(nc).append(":  ");
              comma = true;
            }
            changedClassesSb.append(methodName).append(" was added");
            continue; // only report one diff per class
          }
          if (goldCode != method.getCode().code.length) {
            if (comma) {
              changedClassesSb.append(", and ");
            } else {
              changedClassesSb.append(nc).append(":  ");
              comma = true;
            }
            changedClassesSb.append(methodName)
                .append(" (len=" + method.getCode().code.length + ",expected=" + goldCode + ")");
            continue;
          }
        }
        for (Map.Entry<String, Integer> entry : gold.methods.entrySet()) {
          if (!nc.methods.containsKey(entry.getKey())) {
            if (comma) {
              changedClassesSb.append(", and ");
            } else {
              changedClassesSb.append(nc).append(":  ");
            }
            changedClassesSb.append(entry.getKey()).append(" is missing");
          }
        }
        if (comma) {
          changedClassesSb.append("\n");
        }
      }
    }
    while (it.hasNext()) {
      newclass = it.next();
      newClassesSb.append(newclass).append(": new class\n");
    }
    String result = "";
    if (newClassesSb.length() > newBase) {
      if (changedClassesSb.length() > changedBase) {
        newClassesSb.append("\n");
        newClassesSb.append(changedClassesSb);
      }
      result = newClassesSb.toString();
    } else if (changedClassesSb.length() > changedBase) {
      result = changedClassesSb.toString();
    }
    return result;
  }

  public static void storeClassesAndMethods(List<ClassAndMethods> cams, File file)
      throws IOException {
    FileWriter fw = new FileWriter(file);
    BufferedWriter out = new BufferedWriter(fw);
    for (ClassAndMethods entry : cams) {
      out.append(ClassAndMethodDetails.convertForStoring(entry));
      out.newLine();
    }
    out.flush();
    out.close();
  }

  public static List<ClassAndVariableDetails> loadClassesAndVariables(File file)
      throws IOException {
    List<ClassAndVariableDetails> result = new LinkedList<ClassAndVariableDetails>();
    FileReader fr = new FileReader(file);
    BufferedReader in = new BufferedReader(fr);
    String line;
    while ((line = in.readLine()) != null) {
      line = line.trim();
      if (line.startsWith("#") || line.startsWith("//")) {
        // comment line
      } else {
        result.add(new ClassAndVariableDetails(line));
      }
    }
    fr.close();
    return result;
  }

  public static String diffSortedClassesAndVariables(List<ClassAndVariableDetails> goldRecord,
      List<ClassAndVariables> cavs) {

    StringBuilder newClassesSb = new StringBuilder(10000);
    StringBuilder changedClassesSb = new StringBuilder(10000);
    newClassesSb.append("New or moved classes----------------------------------------\n");
    int newBase = newClassesSb.length();
    changedClassesSb.append("Modified classes--------------------------------------------\n");
    int changedBase = changedClassesSb.length();

    Iterator<ClassAndVariables> it = cavs.iterator();
    ClassAndVariables newclass = null;

    List<String> added = new ArrayList<>();
    List<String> removed = new ArrayList<>();
    List<String> changed = new ArrayList<>();

    for (ClassAndVariableDetails gold : goldRecord) {
      added.clear();
      removed.clear();
      changed.clear();
      if (newclass == null) {
        if (!it.hasNext()) {
          changedClassesSb.append(gold).append(": deleted or moved\n");
          continue;
        }
        newclass = it.next();
      }
      int comparison = -1;
      while (newclass != null
          && (comparison = gold.className.compareTo(newclass.dclass.fullyQualifiedName())) > 0) {
        newClassesSb.append(ClassAndVariableDetails.convertForStoring(newclass)).append("\n");
        newclass = null;
        if (it.hasNext()) {
          newclass = it.next();
        }
      }
      if (comparison == 0) {
        ClassAndVariables nc = newclass;
        newclass = null;
        for (Map.Entry<String, CompiledField> entry : nc.variables.entrySet()) {
          CompiledField field = entry.getValue();
          String name = entry.getKey();
          String type = gold.variables.get(name);
          if (type == null) {
            added.add(name);
            continue; // only report one diff per class
          }
          String newType = field.descriptor();
          if (!newType.equals(type)) {
            changed.add(name + " type changed to " + newType);
            continue;
          }
        }
        for (Map.Entry<String, String> entry : gold.variables.entrySet()) {
          if (!nc.variables.containsKey(entry.getKey())) {
            removed.add(entry.getKey());
          }
        }
        if (!(added.isEmpty() && removed.isEmpty() && changed.isEmpty())) {
          changedClassesSb.append(nc).append('\n');
        }
        if (!added.isEmpty()) {
          changedClassesSb.append("\t\t added fields: ").append(added).append('\n');
        }
        if (!changed.isEmpty()) {
          changedClassesSb.append("\t\t changed fields: ").append(changed).append('\n');
        }
        if (gold.hasSerialVersionUID) {
          if (nc.hasSerialVersionUID) {
            if (!Long.valueOf(gold.serialVersionUID).equals(nc.serialVersionUID)) {
              changedClassesSb.append("\t\t " + nc.dclass.fullyQualifiedName()
                  + " serialVersionUID was changed from " + gold.serialVersionUID + " to "
                  + nc.serialVersionUID
                  + " this may break client/server compatibility as well as server/server compatibility \n");
            }
          } else {
            changedClassesSb.append("\t\t " + nc.dclass.fullyQualifiedName()
                + " serialVersionUID was removed, this may break client/server compatibility as well as server/server compatibility \n");
          }
        } else {
          if (nc.hasSerialVersionUID) {
            changedClassesSb.append(
                "\t\t " + nc.dclass.fullyQualifiedName() + " serialVersionUID was added \n");
          }
        }
      }
    }
    while (it.hasNext()) {
      newclass = it.next();
      newClassesSb.append(ClassAndVariableDetails.convertForStoring(newclass))
          .append(": new class\n");
    }
    String result = "";
    if (newClassesSb.length() > newBase) {
      if (changedClassesSb.length() > changedBase) {
        newClassesSb.append("\n");
        newClassesSb.append(changedClassesSb);
      }
      result = newClassesSb.toString();
    } else if (changedClassesSb.length() > changedBase) {
      result = changedClassesSb.toString();
    }
    return result;
  }

  public static void storeClassesAndVariables(List<ClassAndVariables> cams, File file)
      throws IOException {
    FileWriter fw = new FileWriter(file);
    BufferedWriter out = new BufferedWriter(fw);
    for (ClassAndVariables entry : cams) {
      out.append(ClassAndVariableDetails.convertForStoring(entry));
      out.newLine();
    }
    out.flush();
    out.close();
  }
}
