
// Jwc.java
// Modified by Andrew Davison, ad@coe.psu.ac.th, June 2023

/* A simplified version of wc
   Man page: https://man7.org/linux/man-pages/man1/wc.1.html

Usage: Jwc [-hlLmVw] [FILE...]
A simple Java version of wc.
      [FILE...]           File(s) to be searched
  -h, --help              Show this help message and exit.
  -l, --lines             print the newlines count
  -L, --max-line-length   print the length of the longest line
  -m, --chars             print the character count
  -V, --version           Print version information and exit.
  -w, --words             print the word count


  Picocli features:
    * named options and positional parameters
    * POSIX-style grouped short options 
    * automatic help and version options
    * exit codes

  Usage examples:
    > compile Jwc.java

    > run Jwc -h
    > run Jwc Jwc.java
    > run Jwc *.java
    > run Jwc -lw Jwc.java
*/



import java.io.*;
import java.util.*;
import java.util.concurrent.*;

import picocli.CommandLine;
import picocli.CommandLine.*;


@Command(name = "Jwc", 
         mixinStandardHelpOptions = true,
         version = "Jwc 1.0",
         description = "A simple Java version of wc.")
public class Jwc implements Callable<Integer>
{

  @CommandLine.Option(names = {"-m", "--chars"},
                      description = "print the character count")
  private boolean getCharCount = false;

  @CommandLine.Option(names = {"-l", "--lines"},
                      description = "print the newlines count")
  private boolean getLineCount = false;

  @CommandLine.Option(names = {"-w", "--words"},
                      description = "print the word count")
  private boolean getWordCount = false;

  @CommandLine.Option(names = {"-L", "--max-line-length"},
              description = "print the length of the longest line")
  private boolean getMaxLen = false;

  @Parameters(index = "0..*",
              paramLabel = "FILE", 
              description = "File(s) to be searched")
  private List<String> fnms;   // could be List<File>


  private int charCountTotal = 0;
  private int lineCountTotal = 0;
  private int wordCountTotal = 0;
  private int largestMaxLen = 0;

  private boolean hasFlags = false;


  public Integer call()
  { 
    if (getCharCount || getLineCount || getWordCount || getMaxLen)
      hasFlags = true;

    if (fnms == null)
      countFile(new InputStreamReader(System.in), "(stdin)");
    else {
      for (String fnm : fnms) {
        try {
          countFile(new FileReader(fnm), fnm);
        }
        catch(Exception e) 
        {   System.err.println(e);  }

        if (fnms.size() > 1) {  // print totals
          if (!hasFlags)
            System.out.printf("%5d %5d %5d total\n", 
                 lineCountTotal, wordCountTotal, charCountTotal);
          else {
            if (getLineCount)
              System.out.printf("%5d ", lineCountTotal);
            if (getWordCount)
              System.out.printf("%5d ", wordCountTotal);
            if (getCharCount)
              System.out.printf("%5d ", charCountTotal);
            if (getMaxLen)
              System.out.printf("%5d ", largestMaxLen);
            System.out.printf("total\n");
          }
        }
      }
    }
    return 0;
  }  // end of call()


  private void countFile(Reader ifile, String fnm)
  // examine a single file
  {
    int charCount = 0;
    int lineCount = 0;
    int wordCount = 0;
    int maxLen = 0;
    String line;

    try {
      BufferedReader br = new BufferedReader(ifile);
      while ((line = br.readLine()) != null) {
        int len = line.length() + System.lineSeparator().length();
        charCount += len;
        lineCount++;
        StringTokenizer st = new StringTokenizer(line);
        wordCount += st.countTokens();
        if (len > maxLen)
          maxLen = len;
      }
      br.close(); // end of file
    }
    catch (IOException e) 
    {  System.err.println(e);  }

    charCountTotal += charCount;
    lineCountTotal += lineCount;
    wordCountTotal += wordCount;
    if (maxLen > largestMaxLen)
      largestMaxLen = maxLen;

    // report counts
    if (!hasFlags)
      System.out.printf("%5d %5d %5d %s\n", 
                     lineCount, wordCount, charCount, fnm);
    else {
      if (getLineCount)
        System.out.printf("%5d ", lineCount);
      if (getWordCount)
        System.out.printf("%5d ", wordCount);
      if (getCharCount)
        System.out.printf("%5d ", charCount);
      if (getMaxLen)
        System.out.printf("%5d ", maxLen);
      System.out.printf("%s\n", fnm);
    }
  } // end of countFile()


  // ---------------------------------------------

  public static void main(String[] args)
  {
    int exitCode = new CommandLine(new Jwc()).execute(args);
    System.exit(exitCode); 
  }

}  // end of Jwc class