package net.minecraft.crash;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import net.minecraft.util.ReportedException;
import net.minecraft.world.gen.layer.IntCache;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class CrashReport
{
  private static final Logger logger = ;
  private final String description;
  private final Throwable cause;
  private final CrashReportCategory theReportCategory = new CrashReportCategory(this, "System Details");
  private final List crashReportSections = new ArrayList();
  private File crashReportFile;
  private boolean field_85059_f = true;
  private StackTraceElement[] stacktrace = new StackTraceElement[0];
  private static final String __OBFID = "CL_00000990";
  
  public CrashReport(String p_i1348_1_, Throwable p_i1348_2_)
  {
    this.description = p_i1348_1_;
    this.cause = p_i1348_2_;
    populateEnvironment();
  }
  
  private void populateEnvironment()
  {
    this.theReportCategory.addCrashSectionCallable("Minecraft Version", new Callable()
    {
      private static final String __OBFID = "CL_00001197";
      
      public String call()
      {
        return "1.8";
      }
    });
    this.theReportCategory.addCrashSectionCallable("Operating System", new Callable()
    {
      private static final String __OBFID = "CL_00001222";
      
      public String call()
      {
        return System.getProperty("os.name") + " (" + System.getProperty("os.arch") + ") version " + System.getProperty("os.version");
      }
    });
    this.theReportCategory.addCrashSectionCallable("Java Version", new Callable()
    {
      private static final String __OBFID = "CL_00001248";
      
      public String call()
      {
        return System.getProperty("java.version") + ", " + System.getProperty("java.vendor");
      }
    });
    this.theReportCategory.addCrashSectionCallable("Java VM Version", new Callable()
    {
      private static final String __OBFID = "CL_00001275";
      
      public String call()
      {
        return System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor");
      }
    });
    this.theReportCategory.addCrashSectionCallable("Memory", new Callable()
    {
      private static final String __OBFID = "CL_00001302";
      
      public String call()
      {
        Runtime var1 = Runtime.getRuntime();
        long var2 = var1.maxMemory();
        long var4 = var1.totalMemory();
        long var6 = var1.freeMemory();
        long var8 = var2 / 1024L / 1024L;
        long var10 = var4 / 1024L / 1024L;
        long var12 = var6 / 1024L / 1024L;
        return var6 + " bytes (" + var12 + " MB) / " + var4 + " bytes (" + var10 + " MB) up to " + var2 + " bytes (" + var8 + " MB)";
      }
    });
    this.theReportCategory.addCrashSectionCallable("JVM Flags", new Callable()
    {
      private static final String __OBFID = "CL_00001329";
      
      public String call()
      {
        RuntimeMXBean var1 = ManagementFactory.getRuntimeMXBean();
        List var2 = var1.getInputArguments();
        int var3 = 0;
        StringBuilder var4 = new StringBuilder();
        Iterator var5 = var2.iterator();
        while (var5.hasNext())
        {
          String var6 = (String)var5.next();
          if (var6.startsWith("-X"))
          {
            if (var3++ > 0) {
              var4.append(" ");
            }
            var4.append(var6);
          }
        }
        return String.format("%d total; %s", new Object[] { Integer.valueOf(var3), var4.toString() });
      }
    });
    this.theReportCategory.addCrashSectionCallable("AABB Pool Size", new Callable()
    {
      private static final String __OBFID = "CL_00001355";
      
      public String call()
      {
        byte var1 = 0;
        int var2 = 56 * var1;
        int var3 = var2 / 1024 / 1024;
        byte var4 = 0;
        int var5 = 56 * var4;
        int var6 = var5 / 1024 / 1024;
        return var1 + " (" + var2 + " bytes; " + var3 + " MB) allocated, " + var4 + " (" + var5 + " bytes; " + var6 + " MB) used";
      }
    });
    this.theReportCategory.addCrashSectionCallable("IntCache", new Callable()
    {
      private static final String __OBFID = "CL_00001382";
      
      public String call()
        throws SecurityException, NoSuchFieldException, IllegalAccessException, IllegalArgumentException
      {
        return IntCache.getCacheSizes();
      }
    });
  }
  
  public String getDescription()
  {
    return this.description;
  }
  
  public Throwable getCrashCause()
  {
    return this.cause;
  }
  
  public void getSectionsInStringBuilder(StringBuilder p_71506_1_)
  {
    if (((this.stacktrace == null) || (this.stacktrace.length <= 0)) && (this.crashReportSections.size() > 0)) {
      this.stacktrace = ((StackTraceElement[])ArrayUtils.subarray(((CrashReportCategory)this.crashReportSections.get(0)).func_147152_a(), 0, 1));
    }
    if ((this.stacktrace != null) && (this.stacktrace.length > 0))
    {
      p_71506_1_.append("-- Head --\n");
      p_71506_1_.append("Stacktrace:\n");
      StackTraceElement[] var2 = this.stacktrace;
      int var3 = var2.length;
      for (int var4 = 0; var4 < var3; var4++)
      {
        StackTraceElement var5 = var2[var4];
        p_71506_1_.append("\t").append("at ").append(var5.toString());
        p_71506_1_.append("\n");
      }
      p_71506_1_.append("\n");
    }
    Iterator var6 = this.crashReportSections.iterator();
    while (var6.hasNext())
    {
      CrashReportCategory var7 = (CrashReportCategory)var6.next();
      var7.appendToStringBuilder(p_71506_1_);
      p_71506_1_.append("\n\n");
    }
    this.theReportCategory.appendToStringBuilder(p_71506_1_);
  }
  
  /* Error */
  public String getCauseStackTraceOrString()
  {
    // Byte code:
    //   0: aconst_null
    //   1: astore_1
    //   2: aconst_null
    //   3: astore_2
    //   4: aload_0
    //   5: getfield 78	net/minecraft/crash/CrashReport:cause	Ljava/lang/Throwable;
    //   8: astore_3
    //   9: aload_3
    //   10: checkcast 194	java/lang/Throwable
    //   13: invokevirtual 197	java/lang/Throwable:getMessage	()Ljava/lang/String;
    //   16: ifnonnull +80 -> 96
    //   19: aload_3
    //   20: instanceof 199
    //   23: ifeq +18 -> 41
    //   26: new 199	java/lang/NullPointerException
    //   29: dup
    //   30: aload_0
    //   31: getfield 76	net/minecraft/crash/CrashReport:description	Ljava/lang/String;
    //   34: invokespecial 202	java/lang/NullPointerException:<init>	(Ljava/lang/String;)V
    //   37: astore_3
    //   38: goto +44 -> 82
    //   41: aload_3
    //   42: instanceof 208
    //   45: ifeq +18 -> 63
    //   48: new 208	java/lang/StackOverflowError
    //   51: dup
    //   52: aload_0
    //   53: getfield 76	net/minecraft/crash/CrashReport:description	Ljava/lang/String;
    //   56: invokespecial 209	java/lang/StackOverflowError:<init>	(Ljava/lang/String;)V
    //   59: astore_3
    //   60: goto +22 -> 82
    //   63: aload_3
    //   64: instanceof 211
    //   67: ifeq +15 -> 82
    //   70: new 211	java/lang/OutOfMemoryError
    //   73: dup
    //   74: aload_0
    //   75: getfield 76	net/minecraft/crash/CrashReport:description	Ljava/lang/String;
    //   78: invokespecial 212	java/lang/OutOfMemoryError:<init>	(Ljava/lang/String;)V
    //   81: astore_3
    //   82: aload_3
    //   83: checkcast 194	java/lang/Throwable
    //   86: aload_0
    //   87: getfield 78	net/minecraft/crash/CrashReport:cause	Ljava/lang/Throwable;
    //   90: invokevirtual 215	java/lang/Throwable:getStackTrace	()[Ljava/lang/StackTraceElement;
    //   93: invokevirtual 219	java/lang/Throwable:setStackTrace	([Ljava/lang/StackTraceElement;)V
    //   96: aload_3
    //   97: checkcast 194	java/lang/Throwable
    //   100: invokevirtual 220	java/lang/Throwable:toString	()Ljava/lang/String;
    //   103: astore 4
    //   105: new 204	java/io/StringWriter
    //   108: dup
    //   109: invokespecial 221	java/io/StringWriter:<init>	()V
    //   112: astore_1
    //   113: new 206	java/io/PrintWriter
    //   116: dup
    //   117: aload_1
    //   118: invokespecial 224	java/io/PrintWriter:<init>	(Ljava/io/Writer;)V
    //   121: astore_2
    //   122: aload_3
    //   123: checkcast 194	java/lang/Throwable
    //   126: aload_2
    //   127: invokevirtual 228	java/lang/Throwable:printStackTrace	(Ljava/io/PrintWriter;)V
    //   130: aload_1
    //   131: invokevirtual 229	java/io/StringWriter:toString	()Ljava/lang/String;
    //   134: astore 4
    //   136: goto +16 -> 152
    //   139: astore 5
    //   141: aload_1
    //   142: invokestatic 236	org/apache/commons/io/IOUtils:closeQuietly	(Ljava/io/Writer;)V
    //   145: aload_2
    //   146: invokestatic 236	org/apache/commons/io/IOUtils:closeQuietly	(Ljava/io/Writer;)V
    //   149: aload 5
    //   151: athrow
    //   152: aload_1
    //   153: invokestatic 236	org/apache/commons/io/IOUtils:closeQuietly	(Ljava/io/Writer;)V
    //   156: aload_2
    //   157: invokestatic 236	org/apache/commons/io/IOUtils:closeQuietly	(Ljava/io/Writer;)V
    //   160: aload 4
    //   162: areturn
    // Line number table:
    //   Java source line #217	-> byte code offset #0
    //   Java source line #218	-> byte code offset #2
    //   Java source line #219	-> byte code offset #4
    //   Java source line #221	-> byte code offset #9
    //   Java source line #223	-> byte code offset #19
    //   Java source line #225	-> byte code offset #26
    //   Java source line #226	-> byte code offset #38
    //   Java source line #227	-> byte code offset #41
    //   Java source line #229	-> byte code offset #48
    //   Java source line #230	-> byte code offset #60
    //   Java source line #231	-> byte code offset #63
    //   Java source line #233	-> byte code offset #70
    //   Java source line #236	-> byte code offset #82
    //   Java source line #239	-> byte code offset #96
    //   Java source line #243	-> byte code offset #105
    //   Java source line #244	-> byte code offset #113
    //   Java source line #245	-> byte code offset #122
    //   Java source line #246	-> byte code offset #130
    //   Java source line #247	-> byte code offset #136
    //   Java source line #249	-> byte code offset #139
    //   Java source line #250	-> byte code offset #141
    //   Java source line #251	-> byte code offset #145
    //   Java source line #252	-> byte code offset #149
    //   Java source line #250	-> byte code offset #152
    //   Java source line #251	-> byte code offset #156
    //   Java source line #254	-> byte code offset #160
    // Local variable table:
    //   start	length	slot	name	signature
    //   0	163	0	this	CrashReport
    //   1	152	1	var1	java.io.StringWriter
    //   3	154	2	var2	java.io.PrintWriter
    //   8	115	3	var3	Object
    //   103	58	4	var4	String
    //   139	11	5	localObject1	Object
    // Exception table:
    //   from	to	target	type
    //   105	139	139	finally
  }
  
  public String getCompleteReport()
  {
    StringBuilder var1 = new StringBuilder();
    var1.append("---- Minecraft Crash Report ----\n");
    var1.append("// ");
    var1.append(getWittyComment());
    var1.append("\n\n");
    var1.append("Time: ");
    var1.append(new SimpleDateFormat().format(new Date()));
    var1.append("\n");
    var1.append("Description: ");
    var1.append(this.description);
    var1.append("\n\n");
    var1.append(getCauseStackTraceOrString());
    var1.append("\n\nA detailed walkthrough of the error, its code path and all known details is as follows:\n");
    for (int var2 = 0; var2 < 87; var2++) {
      var1.append("-");
    }
    var1.append("\n\n");
    getSectionsInStringBuilder(var1);
    return var1.toString();
  }
  
  public File getFile()
  {
    return this.crashReportFile;
  }
  
  public boolean saveToFile(File p_147149_1_)
  {
    if (this.crashReportFile != null) {
      return false;
    }
    if (p_147149_1_.getParentFile() != null) {
      p_147149_1_.getParentFile().mkdirs();
    }
    try
    {
      FileWriter var2 = new FileWriter(p_147149_1_);
      var2.write(getCompleteReport());
      var2.close();
      this.crashReportFile = p_147149_1_;
      return true;
    }
    catch (Throwable var3)
    {
      logger.error("Could not save crash report to " + p_147149_1_, var3);
    }
    return false;
  }
  
  public CrashReportCategory getCategory()
  {
    return this.theReportCategory;
  }
  
  public CrashReportCategory makeCategory(String p_85058_1_)
  {
    return makeCategoryDepth(p_85058_1_, 1);
  }
  
  public CrashReportCategory makeCategoryDepth(String p_85057_1_, int p_85057_2_)
  {
    CrashReportCategory var3 = new CrashReportCategory(this, p_85057_1_);
    if (this.field_85059_f)
    {
      int var4 = var3.getPrunedStackTrace(p_85057_2_);
      StackTraceElement[] var5 = this.cause.getStackTrace();
      StackTraceElement var6 = null;
      StackTraceElement var7 = null;
      int var8 = var5.length - var4;
      if (var8 < 0) {
        System.out.println("Negative index in crash report handler (" + var5.length + "/" + var4 + ")");
      }
      if ((var5 != null) && (var8 >= 0) && (var8 < var5.length))
      {
        var6 = var5[var8];
        if (var5.length + 1 - var4 < var5.length) {
          var7 = var5[(var5.length + 1 - var4)];
        }
      }
      this.field_85059_f = var3.firstTwoElementsOfStackTraceMatch(var6, var7);
      if ((var4 > 0) && (!this.crashReportSections.isEmpty()))
      {
        CrashReportCategory var9 = (CrashReportCategory)this.crashReportSections.get(this.crashReportSections.size() - 1);
        var9.trimStackTraceEntriesFromBottom(var4);
      }
      else if ((var5 != null) && (var5.length >= var4) && (var8 >= 0) && (var8 < var5.length))
      {
        this.stacktrace = new StackTraceElement[var8];
        System.arraycopy(var5, 0, this.stacktrace, 0, this.stacktrace.length);
      }
      else
      {
        this.field_85059_f = false;
      }
    }
    this.crashReportSections.add(var3);
    return var3;
  }
  
  private static String getWittyComment()
  {
    String[] var0 = { "Who set us up the TNT?", "Everything's going to plan. No, really, that was supposed to happen.", "Uh... Did I do that?", "Oops.", "Why did you do that?", "I feel sad now :(", "My bad.", "I'm sorry, Dave.", "I let you down. Sorry :(", "On the bright side, I bought you a teddy bear!", "Daisy, daisy...", "Oh - I know what I did wrong!", "Hey, that tickles! Hehehe!", "I blame Dinnerbone.", "You should try our sister game, Minceraft!", "Don't be sad. I'll do better next time, I promise!", "Don't be sad, have a hug! <3", "I just don't know what went wrong :(", "Shall we play a game?", "Quite honestly, I wouldn't worry myself about that.", "I bet Cylons wouldn't have this problem.", "Sorry :(", "Surprise! Haha. Well, this is awkward.", "Would you like a cupcake?", "Hi. I'm Minecraft, and I'm a crashaholic.", "Ooh. Shiny.", "This doesn't make any sense!", "Why is it breaking :(", "Don't do that.", "Ouch. That hurt :(", "You're mean.", "This is a token for 1 free hug. Redeem at your nearest Mojangsta: [~~HUG~~]", "There are four lights!", "But it works on my machine." };
    try
    {
      return var0[((int)(System.nanoTime() % var0.length))];
    }
    catch (Throwable var2) {}
    return "Witty comment unavailable :(";
  }
  
  public static CrashReport makeCrashReport(Throwable p_85055_0_, String p_85055_1_)
  {
    CrashReport var2;
    CrashReport var2;
    if ((p_85055_0_ instanceof ReportedException)) {
      var2 = ((ReportedException)p_85055_0_).getCrashReport();
    } else {
      var2 = new CrashReport(p_85055_1_, p_85055_0_);
    }
    return var2;
  }
}