package com.sun.identity.shared.debug.impl;

import com.sun.identity.shared.configuration.SystemPropertiesManager;
import com.sun.identity.shared.debug.IDebug;
import com.sun.identity.shared.locale.Locale;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;

public class DebugImpl implements IDebug {
   private static final String CONFIG_DEBUG_DIRECTORY = "com.iplanet.services.debug.directory";
   private static final String CONFIG_DEBUG_LEVEL = "com.iplanet.services.debug.level";
   private static final String CONFIG_DEBUG_MERGEALL = "com.sun.services.debug.mergeall";
   private static final String CONFIG_DEBUG_MERGEALL_FILE = "debug.out";
   private static final String CONFIG_DEBUG_FILEMAP = "/debugfiles.properties";
   private static final Map<String, PrintWriter> MERGED_WRITERS = new HashMap<>();
   private static Properties debugFileNames;
   private String debugName;
   private int debugLevel = 4;
   private PrintWriter debugWriter;
   private final PrintWriter stdoutWriter = new PrintWriter(System.out, true, StandardCharsets.UTF_8);
   private final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss:SSS a zzz");
   private String debugFilePath;
   private static boolean mergeAllMode;

   public DebugImpl(String debugName) {
      this.setName(debugName);
      this.setDebug(SystemPropertiesManager.get("com.iplanet.services.debug.level"));
      String mf = SystemPropertiesManager.get("com.sun.services.debug.mergeall");
      mergeAllMode = mf != null && mf.equals("on");
   }

   private synchronized void initialize() {
      if (this.debugWriter == null) {
         String debugDirectory = SystemPropertiesManager.get("com.iplanet.services.debug.directory");
         boolean directoryAvailable = false;
         if (debugDirectory != null && !debugDirectory.trim().isEmpty()) {
            File dir = new File(debugDirectory);
            if (!dir.exists()) {
               directoryAvailable = dir.mkdirs();
            } else if (dir.isDirectory() && dir.canWrite()) {
               directoryAvailable = true;
            }
         }

         if (!directoryAvailable) {
            ResourceBundle bundle = Locale.getInstallResourceBundle("amUtilMsgs");
            System.err.println(bundle.getString("com.iplanet.services.debug.nodir"));
            return;
         }

         this.resolveDebugFile(debugDirectory);
         String prefix = this.debugName + ":" + this.dateFormat.format(new Date()) + ": " + Thread.currentThread();
         this.debugWriter = MERGED_WRITERS.get(this.debugFilePath);

         try {
            if (this.debugWriter == null) {
               synchronized (MERGED_WRITERS) {
                  if (this.debugWriter == null) {
                     this.debugWriter = new PrintWriter(new FileWriter(this.debugFilePath, true), true);
                     MERGED_WRITERS.put(this.debugFilePath, this.debugWriter);
                  }
               }
            }

            this.writeIt(prefix, "**********************************************", null);
         } catch (IOException ioex) {
            this.setDebug(4);
            ResourceBundle bundle = Locale.getInstallResourceBundle("amUtilMsgs");
            System.err.println(bundle.getString("com.iplanet.services.debug.nofile"));
            ioex.printStackTrace(System.err);
            if (this.debugWriter != null) {
               try {
                  this.debugWriter.close();
               } catch (Exception var7) {
               }
            }
         }
      }
   }

   @Override
   public String getName() {
      return this.debugName;
   }

   @Override
   public int getState() {
      return this.debugLevel;
   }

   @Override
   public void setDebug(int level) {
      switch (level) {
         case 0:
         case 1:
         case 2:
         case 3:
         case 4:
            this.debugLevel = level;
      }
   }

   @Override
   public void resetDebug(String mf) {
      mergeAllMode = mf != null && mf.equals("on");
      this.debugWriter = null;
   }

   @Override
   public void setDebug(String strDebugLevel) {
      int debugLevel = 4;
      if (strDebugLevel != null && !strDebugLevel.trim().isEmpty()) {
         debugLevel = switch (strDebugLevel) {
            case "off" -> 0;
            case "error" -> 1;
            case "warning" -> 2;
            case "message" -> 3;
            default -> debugLevel;
         };
      }

      this.setDebug(debugLevel);
   }

   @Override
   public boolean messageEnabled() {
      return this.debugLevel > 2;
   }

   @Override
   public boolean warningEnabled() {
      return this.debugLevel > 1;
   }

   @Override
   public boolean errorEnabled() {
      return this.debugLevel > 0;
   }

   @Override
   public void message(String message, Throwable th) {
      if (this.messageEnabled()) {
         this.record(message, th);
      }
   }

   @Override
   public void warning(String message, Throwable th) {
      if (this.warningEnabled()) {
         this.record("WARNING: " + message, th);
      }
   }

   @Override
   public void error(String message, Throwable th) {
      if (this.errorEnabled()) {
         this.record("ERROR: " + message, th);
      }
   }

   private void record(String msg, Throwable th) {
      String prefix = this.debugName + ":" + this.dateFormat.format(new Date()) + ": " + Thread.currentThread();
      this.writeIt(prefix, msg, th);
   }

   private void writeIt(String prefix, String msg, Throwable th) {
      if (this.debugLevel == 4) {
         this.writeIt(this.stdoutWriter, prefix, msg, th);
      } else {
         if (this.debugWriter == null) {
            this.initialize();
         }

         if (this.debugWriter != null) {
            this.writeIt(this.debugWriter, prefix, msg, th);
         } else {
            this.writeIt(this.stdoutWriter, prefix, "DebugWriter is null.", th);
            this.writeIt(this.stdoutWriter, prefix, msg, th);
         }
      }
   }

   private void writeIt(PrintWriter writer, String prefix, String msg, Throwable th) {
      StringBuffer buf = new StringBuffer(prefix);
      buf.append('\n');
      buf.append(msg);
      if (th != null) {
         buf.append('\n');
         StringWriter stBuf = new StringWriter(300);
         PrintWriter stackStream = new PrintWriter(stBuf);
         th.printStackTrace(stackStream);
         stackStream.flush();
         buf.append(stBuf);
      }

      writer.println(buf);
   }

   private void setName(String debugName) {
      this.debugName = debugName;
   }

   private PrintWriter getStdoutWriter() {
      return this.stdoutWriter;
   }

   private void resolveDebugFile(String debugDirectory) {
      if (mergeAllMode) {
         this.debugFilePath = debugDirectory + File.separator + "debug.out";
      } else {
         if (debugFileNames == null) {
            synchronized (MERGED_WRITERS) {
               if (debugFileNames == null) {
                  debugFileNames = new Properties();

                  try {
                     InputStream is = this.getClass().getResourceAsStream("/debugfiles.properties");
                     debugFileNames.load(is);
                  } catch (Exception var5) {
                  }
               }
            }
         }

         String nm = debugFileNames.getProperty(this.debugName);
         if (nm != null) {
            this.debugFilePath = debugDirectory + File.separator + nm;
         } else {
            this.debugFilePath = debugDirectory + File.separator + this.debugName;
         }
      }
   }
}
