/*
 * Licensed 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.jutils.jhardware.util;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** @author Javier Garcia Alonso */
public class HardwareInfoUtils {

  private static final String CRLF = "\r\n";

  private static final String NOT_FOUND = "NOT_FOUND";

  private static final Logger log = Logger.getLogger(HardwareInfoUtils.class.getName());

  // Hide constructor
  private HardwareInfoUtils() {}

  public static List<String> readFile(String filePath) {
    Path path = Paths.get(filePath);

    List<String> fileLines = new ArrayList<>();
    try (BufferedReader reader = new BufferedReader(new FileReader(path.toFile()))) {
      String line;
      while (null != (line = reader.readLine())) {
        fileLines.add(line);
      }
    } catch (IOException ex) {
      log.log(Level.SEVERE, "Unable to read file " + filePath, ex);
    }

    return fileLines;
  }

  public static String getSingleValueFromFile(String filePath) {
    try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
      return reader.readLine();
    } catch (IOException ex) {
      log.log(Level.SEVERE, "Unable to read file " + filePath, ex);
      return null;
    }
  }

  public static String executeCommand(String... command) {
    String commandOutput = null;

    try {
      ProcessBuilder processBuilder = new ProcessBuilder(command);
      processBuilder.redirectErrorStream(true); // redirect error stream to output stream

      commandOutput = readData(processBuilder.start());
    } catch (IOException ex) {
      Logger.getLogger(HardwareInfoUtils.class.getName()).log(Level.SEVERE, null, ex);
    }

    return commandOutput;
  }

  private static String readData(Process process) {
    StringBuilder commandOutput = new StringBuilder();
    BufferedReader processOutput = null;

    try {
      processOutput = new BufferedReader(new InputStreamReader(process.getInputStream()));

      String line;
      while ((line = processOutput.readLine()) != null) {
        if (!line.isEmpty()) {
          commandOutput.append(line).append(CRLF);
        }
      }
    } catch (IOException ex) {
      Logger.getLogger(HardwareInfoUtils.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
      try {
        if (processOutput != null) {
          processOutput.close();
        }
      } catch (IOException ioe) {
        Logger.getLogger(HardwareInfoUtils.class.getName()).log(Level.SEVERE, null, ioe);
      }
    }

    return commandOutput.toString();
  }

  public static boolean isSudo() {
    return executeCommand("sudo", "-n", "true").length() == 0;
  }

  public static String toCamelCase(String s) {
    String[] parts = s.split("_");
    String camelCaseString = "";
    for (String part : parts) {
      camelCaseString = camelCaseString + toProperCase(part);
    }
    return camelCaseString;
  }

  private static String toProperCase(String s) {
    return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
  }

  public static String removeAllSpaces(String s) {
    return s.replaceAll("\\s+", "");
  }

  public static String extractText(String text, String regex) {
    if (text.trim().isEmpty()) {
      return NOT_FOUND;
    }

    final Pattern pattern = Pattern.compile(regex);
    final Matcher matcher = pattern.matcher(text);

    matcher.find();
    if (matcher.groupCount() > 0) {
      return matcher.group(1);
    }
    return NOT_FOUND;
  }
}
