/*
 * 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.internal.logging;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;

import org.apache.geode.LogWriter;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.OSProcess;
import org.apache.geode.internal.io.MainWithChildrenRollingFileHandler;
import org.apache.geode.internal.io.RollingFileHandler;
import org.apache.geode.internal.util.LogFileUtils;
import org.apache.geode.logging.internal.spi.LogConfig;
import org.apache.geode.logging.internal.spi.LogFileDetails;

/**
 * Implementation of {@link LogWriter} for distributed system members. It's just like {@link
 * org.apache.geode.internal.logging.LocalLogWriter} except it has support for rolling and alerts.
 *
 * @since Geode 1.0
 */
public class ManagerLogWriter extends LocalLogWriter implements LogFileDetails {

  private static final String TEST_FILE_SIZE_LIMIT_IN_KB_PROPERTY =
      DistributionConfig.GEMFIRE_PREFIX + "logging.test.fileSizeLimitInKB";

  private final boolean fileSizeLimitInKB;

  private final RollingFileHandler rollingFileHandler;

  private LogConfig config;

  private LocalLogWriter mainLogWriter = this;

  private File logDir;
  private int mainLogId = -1;
  private int childId;
  private boolean useChildLogging;

  /**
   * Set to true when roll is in progress
   */
  private boolean rolling;
  private boolean mainLog = true;

  private File activeLogFile;

  private boolean started;

  private final boolean loner;

  /**
   * Creates a writer that logs to <code>printStream</code>.
   *
   * @param level only messages greater than or equal to this value will be logged.
   * @param printStream is the stream that message will be printed to.
   * @param loner if the distributed member is not part of a cluster
   *
   * @throws IllegalArgumentException if level is not in legal range
   */
  public ManagerLogWriter(final int level, final PrintStream printStream, final boolean loner) {
    this(level, printStream, null, loner);
  }

  /**
   * Creates a writer that logs to <code>printStream</code>.
   *
   * @param level only messages greater than or equal to this value will be logged.
   * @param printStream is the stream that message will be printed to.
   * @param connectionName Name of the connection associated with this logger
   * @param loner if the distributed member is not part of a cluster
   *
   * @throws IllegalArgumentException if level is not in legal range
   *
   * @since GemFire 3.5
   */
  public ManagerLogWriter(final int level, final PrintStream printStream,
      final String connectionName, final boolean loner) {
    super(level, printStream, connectionName);
    fileSizeLimitInKB = Boolean.getBoolean(TEST_FILE_SIZE_LIMIT_IN_KB_PROPERTY);
    rollingFileHandler = new MainWithChildrenRollingFileHandler();
    this.loner = loner;
  }

  /**
   * Sets the config that should be used by this manager to decide how to manage its logging.
   */
  public void setConfig(final LogConfig config) {
    this.config = config;
    configChanged();
  }

  public LogConfig getConfig() {
    return config;
  }

  /**
   * Call when the config changes at runtime.
   */
  public void configChanged() {
    setLevel(config.getLogLevel());
    useChildLogging = config.getLogFile() != null && !config.getLogFile().equals(new File(""))
        && config.getLogFileSizeLimit() != 0;

    if (useChildLogging()) {
      logDir = rollingFileHandler.getParentFile(config.getLogFile());
      // let archive id always follow main log id, not the vice versa
      // e.g. in getArchiveName(), it's using mainArchiveId = calcNextMainId(archiveDir);
      // This is the only place we assign mainLogId.
      // mainLogId is only referenced when useChildLogging==true
      mainLogId = rollingFileHandler.calcNextMainId(logDir, true);
    }
    if (started) {
      if (useChildLogging()) {
        if (mainLog) {
          rollLog();
        }
      } else {
        switchLogs(config.getLogFile(), true);
      }
    }
  }

  @Override
  public File getChildLogFile() {
    return activeLogFile;
  }

  @Override
  public File getLogDir() {
    return logDir;
  }

  @Override
  public int getMainLogId() {
    return mainLogId;
  }

  @Override
  public boolean useChildLogging() {
    return useChildLogging;
  }

  private File getNextChildLogFile() {
    String path = config.getLogFile().getPath();
    int extIndex = path.lastIndexOf('.');
    String ext = "";
    if (extIndex != -1) {
      ext = path.substring(extIndex);
      path = path.substring(0, extIndex);
    }
    path = path + rollingFileHandler.formatId(mainLogId) + rollingFileHandler.formatId(childId)
        + ext;
    childId++;
    File result = new File(path);
    if (result.exists()) {
      // try again until a unique name is found
      return getNextChildLogFile();
    } else {
      return result;
    }
  }

  private long getLogFileSizeLimit() {
    if (rolling || mainLog) {
      return Long.MAX_VALUE;
    } else {
      long result = config.getLogFileSizeLimit();
      if (result == 0) {
        return Long.MAX_VALUE;
      }
      if (fileSizeLimitInKB) {
        // use KB instead of MB to speed up log rolling for test purpose
        return result * 1024;
      } else {
        return result * (1024 * 1024);
      }
    }
  }

  private long getLogDiskSpaceLimit() {
    long result = config.getLogDiskSpaceLimit();
    return result * (1024 * 1024);
  }

  private String getMetaLogFileName(final String baseLogFileName, final int mainLogId) {
    String metaLogFile = null;
    int extIndex = baseLogFileName.lastIndexOf('.');
    String ext = "";
    if (extIndex != -1) {
      ext = baseLogFileName.substring(extIndex);
      metaLogFile = baseLogFileName.substring(0, extIndex);
    }
    String fileName = new File(metaLogFile).getName();
    String parent = new File(metaLogFile).getParent();

    metaLogFile = "meta-" + fileName + rollingFileHandler.formatId(mainLogId) + ext;
    if (parent != null) {
      metaLogFile = parent + File.separator + metaLogFile;
    }
    return metaLogFile;
  }

  private synchronized void switchLogs(final File newLog, final boolean newIsMain) {
    rolling = true;
    try {
      try {
        if (!newIsMain) {
          if (mainLog && mainLogWriter == this && config.getLogFile() != null) {
            // this is the first child. Save the current output stream
            // so we can log special messages to the main log instead
            // of the current child log.
            String metaLogFile =
                getMetaLogFileName(config.getLogFile().getPath(), mainLogId);
            mainLogWriter = new LocalLogWriter(INFO_LEVEL,
                new PrintStream(new FileOutputStream(metaLogFile, true), true));
            if (activeLogFile == null) {
              mainLogWriter.info(String.format("Switching to log %s",
                  config.getLogFile()));
            }
          } else {
            mainLogWriter.info(String.format("Rolling current log to %s", newLog));
          }
        }
        boolean renameOK = true;
        String oldName = config.getLogFile().getAbsolutePath();
        File tempFile = null;
        if (activeLogFile != null) {
          // is a bug that we get here and try to rename the activeLogFile
          // to a newLog of the same name? This works ok on Unix but on windows fails.
          if (!activeLogFile.getAbsolutePath().equals(newLog.getAbsolutePath())) {
            boolean isWindows = false;
            String os = System.getProperty("os.name");
            if (os != null) {
              if (os.contains("Windows")) {
                isWindows = true;
              }
            }
            if (isWindows) {
              // For windows to work we need to redirect everything
              // to a temporary file so we can get oldFile closed down
              // so we can rename it. We don't actually write to this tmp file
              File tempLogDir = rollingFileHandler.getParentFile(config.getLogFile());
              tempFile = File.createTempFile("mlw", null, tempLogDir);
              // close the old print writer down before we do the rename
              // do not redirect if loner -- see #49492
              PrintStream tempPrintStream = OSProcess.redirectOutput(tempFile, !loner);
              PrintWriter oldPrintWriter = setTarget(new PrintWriter(tempPrintStream, true));
              if (oldPrintWriter != null) {
                oldPrintWriter.close();
              }
            }
            File oldFile = activeLogFile;
            renameOK = LogFileUtils.renameAggressively(oldFile, newLog.getAbsoluteFile());
            if (!renameOK) {
              mainLogWriter
                  .warning("Could not delete original file '" + oldFile + "' after copying to '"
                      + newLog.getAbsoluteFile() + "'. Continuing without rolling.");
            } else {
              renameOK = true;
            }
          }
        }
        activeLogFile = new File(oldName);
        // Don't redirect sysouts/syserrs to client log file. See #49492.
        // IMPORTANT: This assumes that only a loner would have sendAlert set to false.
        PrintStream printStream = OSProcess.redirectOutput(activeLogFile, !loner);
        PrintWriter oldPrintWriter =
            setTarget(new PrintWriter(printStream, true), activeLogFile.length());
        if (oldPrintWriter != null) {
          oldPrintWriter.close();
        }
        if (tempFile != null) {
          tempFile.delete();
        }
        mainLog = newIsMain;
        if (mainLogWriter == null) {
          mainLogWriter = this;
        }
        if (!renameOK) {
          mainLogWriter.warning("Could not rename \"" + activeLogFile + "\" to \"" + newLog
              + "\". Continuing without rolling.");
        }
      } catch (IOException ex) {
        mainLogWriter.warning("Could not open log \"" + newLog + "\" because " + ex);
      }
      checkDiskSpace(activeLogFile);
    } finally {
      rolling = false;
    }
  }

  /**
   * notification from manager that the output file is being closed
   */
  public void closingLogFile() {
    OutputStream nullOutputStream = new OutputStream() {
      @Override
      public void write(int b) throws IOException {
        // --> /dev/null
      }
    };
    close();
    if (mainLogWriter != null) {
      mainLogWriter.close();
    }
    PrintWriter printWriter = setTarget(new PrintWriter(nullOutputStream, true));
    if (printWriter != null) {
      printWriter.close();
    }
  }

  public static File getLogNameForOldMainLog(final File log, final boolean useOldFile) {
    // this is just searching for the existing logfile name we need to search for meta log file name
    RollingFileHandler rollingFileHandler = new MainWithChildrenRollingFileHandler();
    File dir = rollingFileHandler.getParentFile(log.getAbsoluteFile());
    int previousMainId = rollingFileHandler.calcNextMainId(dir, true);
    if (useOldFile) {
      if (previousMainId > 0) {
        previousMainId--;
      }
    }
    if (previousMainId == 0) {
      previousMainId = 1;
    }

    int childId = rollingFileHandler.calcNextChildId(log, previousMainId > 0 ? previousMainId : 0);
    StringBuilder sb = new StringBuilder(log.getPath());
    int insertIdx = sb.lastIndexOf(".");
    if (insertIdx == -1) {
      sb.append(rollingFileHandler.formatId(previousMainId))
          .append(rollingFileHandler.formatId(childId));
    } else {
      sb.insert(insertIdx, rollingFileHandler.formatId(childId));
      sb.insert(insertIdx, rollingFileHandler.formatId(previousMainId));
    }
    return new File(sb.toString());
  }

  private void checkDiskSpace(final File newLog) {
    rollingFileHandler.checkDiskSpace("log", newLog, getLogDiskSpaceLimit(), logDir, mainLogWriter);
  }

  private void rollLog() {
    rollLog(false);
  }

  private void rollLogIfFull() {
    rollLog(true);
  }

  private void rollLog(final boolean ifFull) {
    if (!useChildLogging()) {
      return;
    }
    synchronized (this) {
      // need to do the activeLogFull call while synchronized
      if (ifFull && !activeLogFull()) {
        return;
      }
      switchLogs(getNextChildLogFile(), false);
    }
  }

  /**
   * Called when manager is done starting up. This is when a child log will be started if rolling is
   * configured.
   */
  public void startupComplete() {
    started = true;
    rollLog();
  }

  /**
   * Called when manager starts shutting down. This is when any current child log needs to be closed
   * and the rest of the logging reverted to the main.
   */
  public void shuttingDown() {
    if (useChildLogging()) {
      switchLogs(config.getLogFile(), true);
    }
  }

  private boolean activeLogFull() {
    long limit = getLogFileSizeLimit();
    if (limit == Long.MAX_VALUE) {
      return false;
    } else {
      return getBytesLogged() >= limit;
    }
  }

  @Override
  public void writeFormattedMessage(final String message) {
    rollLogIfFull();
    super.writeFormattedMessage(message);
  }
}
