/*
 * 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;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InvalidClassException;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.geode.DataSerializable;
import org.apache.geode.DataSerializer;
import org.apache.geode.GemFireIOException;
import org.apache.geode.SystemIsRunningException;
import org.apache.geode.UncreatedSystemException;
import org.apache.geode.UnstartedSystemException;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.logging.internal.OSProcess;

/**
 * Represents the information about the manager that is stored in its SystemAdmin manager VM's main
 * thread.
 * <p>
 * For internal use only.
 *
 *
 */
public class ManagerInfo implements DataSerializable {
  private static final long serialVersionUID = 5792809580026325378L;
  /**
   * The name of the file the locator will create when the system is started. It will be deleted
   * when the system is stopped. It contains a single serialize copy of {@link ManagerInfo}. The
   * file will always be located in the system directory.
   */
  private static final String LOCATOR_INFO_FILE_NAME = ".locator";
  /**
   * The status code constant that means the system is stopped.
   * <p>
   * Current value is <code>0</code>.
   */
  public static final int STOPPED_STATUS_CODE = 0;
  /**
   * The status code constant that means the system is stopping.
   * <p>
   * Current value is <code>1</code>.
   */
  public static final int STOPPING_STATUS_CODE = 1;
  /**
   * The status code constant that means the system was killed.
   * <p>
   * Current value is <code>2</code>.
   */
  public static final int KILLED_STATUS_CODE = 2;
  /**
   * The status code constant that means the system is starting.
   * <p>
   * Current value is <code>3</code>.
   */
  public static final int STARTING_STATUS_CODE = 3;
  /**
   * The status code constant that means the system is started.
   * <p>
   * Current value is <code>4</code>.
   */
  public static final int STARTED_STATUS_CODE = 4;

  public static void setLocatorStarted(File directory, int port, InetAddress bindAddress) {
    ManagerInfo.saveManagerInfo(OSProcess.getId(), STARTED_STATUS_CODE, directory, port,
        bindAddress);
  }

  public static File setLocatorStarting(File directory, int port, InetAddress bindAddress) {
    if (ManagerInfo.isManagerRunning(directory, true)) {
      throw new SystemIsRunningException(String.format("%s %s is already running.",
          new Object[] {"Locator", directory.getPath()}));
    }
    File result = getManagerInfoFile(directory, true);
    ManagerInfo.saveManagerInfo(OSProcess.getId(), STARTING_STATUS_CODE, directory, port,
        bindAddress);
    return result;
  }

  // fix for bug #44059. store the port and address for the locator in the persistent information
  // so we can use "-dir" to stop the locator.
  public static void setLocatorStopping(File directory, int port, InetAddress bindAddress) {
    ManagerInfo.saveManagerInfo(OSProcess.getId(), STOPPING_STATUS_CODE, directory, port,
        bindAddress);
  }

  /**
   * Saves the manager information to the info file in the given <code>directory</code>.
   *
   * @param pid the process id of the manager VM.
   * @param status the status of the manager
   * @param directory the manager's directory.
   * @param port the tcp/ip port for the locator
   * @param bindAddress the tcp/ip address for the locator
   * @throws GemFireIOException if the file could not be written.
   */
  private static void saveManagerInfo(int pid, int status, File directory, int port,
      InetAddress bindAddress) {
    ManagerInfo info = new ManagerInfo(pid, status, port, bindAddress);
    File infoFile = getManagerInfoFile(directory, true);
    try {
      FileOutputStream ostream = new FileOutputStream(infoFile);
      DataOutputStream dos = new DataOutputStream(ostream);
      DataSerializer.writeObject(info, dos);
      ostream.close();
    } catch (IOException io) {
      throw new GemFireIOException(
          String.format("Could not write file %s.", infoFile), io);
    }
  }

  /**
   * Gets the process ID of the manager.
   */
  public int getManagerProcessId() {
    return this.managerPid;
  }

  /**
   * Gets the status of the manager.
   */
  public int getManagerStatus() {
    return this.managerStatus;
  }

  /**
   * get the port number of the manager
   */
  public int getManagerPort() {
    return this.port;
  }

  /**
   * get the bind address of the manager
   */
  public InetAddress getManagerAddress() {
    return this.bindAddress;
  }

  @Immutable
  static final List<String> statusNames =
      Collections.unmodifiableList(Arrays.asList("stopped",
          "stopping",
          "killed",
          "starting",
          "running"));

  /**
   * Gets the string representation for the given <code>status</code> int code.
   */
  public static String statusToString(int status) {
    return statusNames.get(status);
  }

  /**
   * Gets the status code for the given <code>statusName</code>.
   *
   * @throws IllegalArgumentException if an unknown status name is given.
   */
  public static int statusNameToCode(String statusName) {
    for (int i = STOPPED_STATUS_CODE; i <= STARTED_STATUS_CODE; i++) {
      if (statusNames.get(i).equalsIgnoreCase(statusName)) {
        return i;
      }
    }
    throw new IllegalArgumentException(
        String.format("Unknown statusName %s", statusName));
  }

  public static ManagerInfo loadLocatorInfo(File directory) {
    return loadManagerInfo(directory, true);
  }

  private static ManagerInfo loadManagerInfo(File directory, boolean locator) {
    if (!directory.exists() || !directory.isDirectory()) {
      throw new UncreatedSystemException(
          String.format("%s does not exist or is not a directory.",
              directory.getPath()));
    }
    File infoFile = getManagerInfoFile(directory, locator);
    if (!infoFile.exists()) {
      throw new UnstartedSystemException(String.format("The info file %s does not exist.",
          infoFile.getPath()));
    }
    try {
      FileInputStream fis = new FileInputStream(infoFile);
      if (fis.available() == 0) {
        throw new GemFireIOException(
            String.format(
                "Could not load file %s because the file is empty. Wait for the %s to finish starting.",
                new Object[] {infoFile, (locator ? "locator" : "system")}),
            null);
      }
      DataInputStream dis = new DataInputStream(fis);
      ManagerInfo result = (ManagerInfo) DataSerializer.readObject(dis);
      fis.close();
      return result;
    } catch (IOException io) {
      throw new GemFireIOException(
          String.format("Could not load file %s.", infoFile), io);
    } catch (ClassNotFoundException ex) {
      throw new GemFireIOException(
          String.format("Could not load file %s because a class could not be found.",
              infoFile),
          ex);
    }
  }

  public static File getLocatorInfoFile(File directory) {
    return getManagerInfoFile(directory, true);
  }

  private static File getManagerInfoFile(File directory, boolean locator) {
    if (!locator) {
      throw new IllegalArgumentException(
          "Only locators are supported");
    }
    File res = new File(directory, LOCATOR_INFO_FILE_NAME);
    try {
      res = res.getCanonicalFile();
    } catch (IOException ex) {
      res = res.getAbsoluteFile();
    }
    return res;
  }

  public static String getLocatorStatusCodeString(File directory) {
    return statusToString(getLocatorStatusCode(directory));
  }

  public static int getLocatorStatusCode(File directory) {
    return getManagerStatusCode(directory, true);
  }

  private static int getManagerStatusCode(File directory, boolean locator) {
    boolean interrupted = false;
    try {
      ManagerInfo mi = ManagerInfo.loadManagerInfo(directory, locator);
      return mi.getManagerStatus();

    } catch (UnstartedSystemException ex) {
      return STOPPED_STATUS_CODE;
    } catch (GemFireIOException ex) {
      // wait a bit and try again in case we caught the manager rewriting
      // its info file
      try {
        Thread.sleep(1000);
      } catch (InterruptedException ignore) {
        interrupted = true;
      }
      try {
        ManagerInfo.loadManagerInfo(directory, locator);
        // all is well so do a recursive call
        return getManagerStatusCode(directory, locator);
      } catch (UnstartedSystemException ignore) {
        return STOPPED_STATUS_CODE;
      }
    } finally {
      if (interrupted) {
        Thread.currentThread().interrupt();
      }
    }
  }

  public static boolean isLocatorStarted(File directory) {
    return isManagerStarted(directory, true);
  }

  private static boolean isManagerStarted(File directory, boolean locator) {
    try {
      ManagerInfo mi = loadManagerInfo(directory, locator);
      int status = mi.getManagerStatus();
      if (status != STARTED_STATUS_CODE) {
        return false;
      }
      return true;
    } catch (UnstartedSystemException ignore) {
      return false;
    } catch (GemFireIOException ex) {
      Throwable cause = ex.getCause();
      if (cause == null) {
        // this happens when the file was zero size
        return false;
      } else if (cause instanceof InvalidClassException) {
        // This happens when we have a serialVersionUID mismatch.
        // We don't want to hide this so throw the exception
        throw ex;
      } else {
        return false;
      }
    }
  }

  public static boolean isLocatorRunning(File directory) {
    return isManagerRunning(directory, true);
  }

  private static boolean isManagerRunning(File directory, boolean locator) {
    try {
      ManagerInfo mi = loadManagerInfo(directory, locator);
      int status = mi.getManagerStatus();
      if (status != STARTED_STATUS_CODE && status != STARTING_STATUS_CODE
          && status != STOPPING_STATUS_CODE) {
        return false;
      }
      return true;
    } catch (UnstartedSystemException ignore) {
      return false;
    } catch (GemFireIOException ex) {
      Throwable cause = ex.getCause();
      if (cause == null) {
        // this happens when the file was zero size
        // This indicates the manager is changing its info file
        return true;
      } else if (cause instanceof InvalidClassException) {
        // This happens when we have a serialVersionUID mismatch.
        // We don't want to hide this so throw the exception
        throw ex;
      } else {
        // This indicates the manager is changing its info file
        return true;
      }
    }
  }

  public static boolean isLocatorStopped(File directory) {
    return isManagerStopped(directory, true);
  }

  private static boolean isManagerStopped(File directory, boolean locator) {
    try {
      ManagerInfo mi = loadManagerInfo(directory, locator);
      if (!OSProcess.exists(mi.getManagerProcessId())) {
        return true;
      }
      return false;
    } catch (UnstartedSystemException ignore) {
      return true;
    } catch (GemFireIOException ex) {
      Throwable cause = ex.getCause();
      if (cause == null) {
        // this happens when the file was zero size
        return false;
      } else if (cause instanceof InvalidClassException) {
        // This happens when we have a serialVersionUID mismatch.
        // We don't want to hide this so throw the exception
        throw ex;
      } else {
        return false;
      }
    }
  }

  /**
   * Constructs a manager info instance given the process id of the manager VM.
   *
   * @param port TODO
   * @param bindAddress TODO
   */
  private ManagerInfo(int pid, int status, int port, InetAddress bindAddress) {
    this.managerPid = pid;
    this.managerStatus = status;
    this.port = port;
    this.bindAddress = bindAddress;
  }

  /**
   * Constructor for <code>DataSerializable</code>
   */
  public ManagerInfo() {}

  // instance variables
  private int managerPid;
  private int managerStatus;
  private int port;
  private InetAddress bindAddress;

  @Override
  public void toData(DataOutput out) throws IOException {
    out.writeInt(this.managerPid);
    out.writeInt(this.managerStatus);
    out.writeInt(this.port);
    if (this.bindAddress == null) {
      out.writeByte(0);
    } else {
      byte[] address = this.bindAddress.getAddress();
      out.writeByte(address.length);
      out.write(address, 0, address.length);
    }
  }

  @Override
  public void fromData(DataInput in) throws IOException, ClassNotFoundException {

    this.managerPid = in.readInt();
    this.managerStatus = in.readInt();
    this.port = in.readInt();
    byte len = in.readByte();
    if (len > 0) {
      byte[] addr = new byte[len];
      in.readFully(addr);
      this.bindAddress = InetAddress.getByAddress(addr);
    }
  }
}
