/*
 * 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.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();
  }
}
