#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <time.h>

volatile sig_atomic_t shutdown_flag = 0;
volatile sig_atomic_t stats_flag = 0;

void handle_sigint(int sig) {
  shutdown_flag = 1;
}

void handle_sigusr1(int sig) {
  stats_flag = 1;
}

int main(int argc, char *argv[]) {
  struct sigaction sa_sigint;
  sa_sigint.sa_handler = handle_sigint;
  sigemptyset(&sa_sigint.sa_mask);
  sa_sigint.sa_flags = 0;
  sigaction(SIGINT, &sa_sigint, NULL);

  struct sigaction sa_sigusr1;
  sa_sigusr1.sa_handler = handle_sigusr1;
  sigemptyset(&sa_sigusr1.sa_mask);
  sa_sigusr1.sa_flags = 0;
  sigaction(SIGUSR1, &sa_sigusr1, NULL);

  int max_lines = -1; // -1 means unlimited
  int verbose = 0;

  // Parse arguments (-n max_lines, -v verbose)
  char opt;
  while ((opt = getopt(argc, argv, "n:v")) != -1) {
    switch (opt) {
    case 'n':
      max_lines = atoi(optarg); break;
    case 'v':
      verbose = 1; break;
    default:
      printf("Usage: %s [-n max_lines] [-v]\n", argv[0]);
      return 1;
    }
  }

  clock_t start = clock();

  // Read from stdin line by line
  // Count lines and characters
  // If verbose, echo lines to stdout
  char buffer[256];
  int lines = 0;
  int chars = 0;
  while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
    int size = strlen(buffer);
    if (verbose)
      fwrite(buffer, sizeof(char), size, stdout);
    chars += size;
    if (size > 0 && buffer[size - 1] == '\n')
      lines++;
    if (lines == max_lines)
      break;

    // Handle shutdown
    if (shutdown_flag) {
      fprintf(stderr, "Cancelled\n");
      return 1;
    }
  }

  // Print statistics to stderr (handle SIGUSR1)
  if (stats_flag) {
    clock_t end = clock();
    double time = ((double)(end - start)) / CLOCKS_PER_SEC;
    double throughput = (double)chars / 1024.0 / 1024.0 / time;
    printf("Stats:\n");
    printf("File Size: %d bytes\n", chars);
    printf("Total Time: %.3f secs\n", time);
    printf("Throughput: %.3f MB/s\n", throughput);
  }
  fprintf(stderr, "Lines: %d\n", lines);

  return 0;
}
