/*
 * 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.management.internal.cli.functions;

import static org.apache.geode.internal.lang.SystemUtils.getOsArchitecture;
import static org.apache.geode.internal.lang.SystemUtils.getOsName;
import static org.apache.geode.internal.lang.SystemUtils.getOsVersion;
import static org.apache.geode.internal.lang.SystemUtils.isLinux;
import static org.apache.geode.internal.lang.SystemUtils.isMacOSX;
import static org.apache.geode.internal.lang.SystemUtils.isSolaris;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.internal.cache.execute.InternalFunction;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.management.internal.cli.CliUtil;
import org.apache.geode.management.internal.cli.CliUtil.DeflaterInflaterData;
import org.apache.geode.management.internal.cli.GfshParser;
import org.apache.geode.management.internal.cli.i18n.CliStrings;

/**
 * Executes 'netstat' OS command & returns the result as compressed bytes.
 *
 * @since GemFire 7.0
 */
@SuppressWarnings({"serial"})
public class NetstatFunction implements InternalFunction {
  private static final Logger logger = LogService.getLogger();
  private static final long serialVersionUID = 1L;

  @Immutable
  public static final NetstatFunction INSTANCE = new NetstatFunction();

  private static final String ID = NetstatFunction.class.getName();

  private static final String NETSTAT_COMMAND = "netstat";
  private static final String LSOF_COMMAND = "lsof";

  @Override
  public boolean hasResult() {
    return true;
  }

  @Override
  public void execute(final FunctionContext context) {
    DistributedSystem ds = InternalDistributedSystem.getConnectedInstance();
    if (ds == null || !ds.isConnected()) {
      return;
    }

    String host = ds.getDistributedMember().getHost();
    NetstatFunctionArgument args = (NetstatFunctionArgument) context.getArguments();
    boolean withlsof = args.isWithlsof();
    String lineSeparator = args.getLineSeparator();

    String netstatOutput = executeCommand(lineSeparator, withlsof);

    StringBuilder netstatInfo = new StringBuilder();

    // {0} will be replaced on Manager
    addMemberHostHeader(netstatInfo, "{0}", host, lineSeparator);

    NetstatFunctionResult result = new NetstatFunctionResult(host, netstatInfo.toString(),
        CliUtil.compressBytes(netstatOutput.getBytes()));

    context.getResultSender().lastResult(result);
  }

  private static void addMemberHostHeader(final StringBuilder netstatInfo, final String id,
      final String host, final String lineSeparator) {

    String osInfo = getOsName() + " " + getOsVersion() + " " + getOsArchitecture();

    StringBuilder memberPlatFormInfo = new StringBuilder();
    memberPlatFormInfo.append(CliStrings.format(CliStrings.NETSTAT__MSG__FOR_HOST_1_OS_2_MEMBER_0,
        new Object[] {id, host, osInfo, lineSeparator}));

    int nameIdLength = Math.max(Math.max(id.length(), host.length()), osInfo.length()) * 2;

    StringBuilder netstatInfoBottom = new StringBuilder();
    for (int i = 0; i < nameIdLength; i++) {
      netstatInfo.append("#");
      netstatInfoBottom.append("#");
    }

    netstatInfo.append(lineSeparator).append(memberPlatFormInfo.toString()).append(lineSeparator)
        .append(netstatInfoBottom.toString()).append(lineSeparator);
  }

  private static void addNetstatDefaultOptions(final List<String> cmdOptionsList) {
    cmdOptionsList.add("-v");
    cmdOptionsList.add("-a");
    cmdOptionsList.add("-n");
    if (isLinux()) {
      cmdOptionsList.add("-e");
    }
  }

  private static void executeNetstat(final StringBuilder netstatInfo, final String lineSeparator) {
    List<String> cmdOptionsList = new ArrayList<>();
    cmdOptionsList.add(NETSTAT_COMMAND);
    addNetstatDefaultOptions(cmdOptionsList);

    if (logger.isDebugEnabled()) {
      logger.debug("NetstatFunction executing {}", cmdOptionsList);
    }

    ProcessBuilder processBuilder = new ProcessBuilder(cmdOptionsList);
    try {
      Process netstat = processBuilder.start();

      InputStream is = netstat.getInputStream();
      BufferedReader breader = new BufferedReader(new InputStreamReader(is));
      String line;

      while ((line = breader.readLine()) != null) {
        netstatInfo.append(line).append(lineSeparator);
      }

      // TODO: move to finally-block
      netstat.destroy();
    } catch (IOException e) {
      // TODO: change this to keep the full stack trace
      netstatInfo.append(CliStrings.format(CliStrings.NETSTAT__MSG__COULD_NOT_EXECUTE_0_REASON_1,
          new Object[] {NETSTAT_COMMAND, e.getMessage()}));
    } finally {
      netstatInfo.append(lineSeparator); // additional new line
    }
  }

  private static void executeLsof(final StringBuilder existingNetstatInfo,
      final String lineSeparator) {
    existingNetstatInfo.append("################ ").append(LSOF_COMMAND)
        .append(" output ###################").append(lineSeparator);

    if (isLinux() || isMacOSX() || isSolaris()) {
      List<String> cmdOptionsList = new ArrayList<>();
      cmdOptionsList.add(LSOF_COMMAND);
      cmdOptionsList.add("-n");
      cmdOptionsList.add("-P");

      ProcessBuilder procBuilder = new ProcessBuilder(cmdOptionsList);
      try {
        Process lsof = procBuilder.start();
        InputStreamReader reader = new InputStreamReader(lsof.getInputStream());
        BufferedReader breader = new BufferedReader(reader);
        String line = "";

        while ((line = breader.readLine()) != null) {
          existingNetstatInfo.append(line).append(lineSeparator);
        }
        // TODO: move this to finally-block
        lsof.destroy();
      } catch (IOException e) {
        // TODO: change this to keep the full stack trace
        String message = e.getMessage();
        if (message.contains("error=2, No such file or directory")) {
          existingNetstatInfo
              .append(CliStrings.format(CliStrings.NETSTAT__MSG__COULD_NOT_EXECUTE_0_REASON_1,
                  new Object[] {LSOF_COMMAND, CliStrings.NETSTAT__MSG__LSOF_NOT_IN_PATH}));
        } else {
          existingNetstatInfo
              .append(CliStrings.format(CliStrings.NETSTAT__MSG__COULD_NOT_EXECUTE_0_REASON_1,
                  new Object[] {LSOF_COMMAND, e.getMessage()}));
        }
      } finally {
        existingNetstatInfo.append(lineSeparator); // additional new line
      }
    } else {
      existingNetstatInfo.append(CliStrings.NETSTAT__MSG__NOT_AVAILABLE_FOR_WINDOWS)
          .append(lineSeparator);
    }
  }

  private static String executeCommand(final String lineSeparator, final boolean withlsof) {
    StringBuilder netstatInfo = new StringBuilder();

    executeNetstat(netstatInfo, lineSeparator);

    if (withlsof) {
      executeLsof(netstatInfo, lineSeparator);
    }

    return netstatInfo.toString();
  }

  @Override
  public String getId() {
    return ID;
  }

  @Override
  public boolean optimizeForWrite() {
    return false;
  }

  @Override
  public boolean isHA() {
    return false;
  }

  public static void main(final String[] args) {
    String netstat = executeCommand(GfshParser.LINE_SEPARATOR, true);
    System.out.println(netstat);
  }

  public static class NetstatFunctionArgument implements Serializable {
    private static final long serialVersionUID = 1L;

    private final String lineSeparator;
    private final boolean withlsof;

    public NetstatFunctionArgument(final String lineSeparator, final boolean withlsof) {
      this.lineSeparator = lineSeparator;
      this.withlsof = withlsof;
    }

    public String getLineSeparator() {
      return lineSeparator;
    }

    public boolean isWithlsof() {
      return withlsof;
    }
  }

  public static class NetstatFunctionResult implements Serializable {
    private static final long serialVersionUID = 1L;

    private final String host;
    private final String headerInfo;
    private final DeflaterInflaterData compressedBytes;

    protected NetstatFunctionResult(final String host, final String headerInfo,
        final DeflaterInflaterData compressedBytes) {
      this.host = host;
      this.headerInfo = headerInfo;
      this.compressedBytes = compressedBytes;
    }

    public String getHost() {
      return host;
    }

    public String getHeaderInfo() {
      return headerInfo;
    }

    public DeflaterInflaterData getCompressedBytes() {
      return compressedBytes;
    }
  }
}
