// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdio.h>
#include <string.h>

#define MAX_WIDTH 40
#define MAX(a, b) ((a > b) ? a : b)
#define MIN(a, b) ((a < b) ? a : b)

// Returns the length of the longst line of the message.
static int LongestLineLength(int argc, char** argv) {
  int max_len = 0;
  int cur_line = 0;

  for (int i = 0; i < argc; i++) {
    int word_len = strlen(argv[i]) + 1;

    // If the word itself is too long to fit in a line, then
    // we return the maximum width.
    if (word_len >= MAX_WIDTH)
      return MAX_WIDTH;

    if (cur_line + word_len >= MAX_WIDTH) {
      cur_line = word_len;
    } else {
      cur_line += word_len;
    }

    max_len = MAX(cur_line, max_len);
  }

  return max_len;
}

static void PrintPaddedBreak(int pad) {
  for (int i = 0; i < pad; i++) {
    printf(" ");
  }
  printf(" |\n");
}

// Prints the message
static void PrintMessage(int argc, char** argv, int longest) {
  int cur_line_len = 0;

  for (int i = 0; i < argc; i++) {
    int word_len = strlen(argv[i]) + 1;

    if (cur_line_len == 0)
      printf("| ");

    // If it all fits in the line, then print the word and move on.
    if (cur_line_len + word_len <= MAX_WIDTH) {
      printf("%s ", argv[i]);

      if (cur_line_len + word_len == MAX_WIDTH) {
        PrintPaddedBreak(longest - cur_line_len - word_len);
        cur_line_len = 0;
        continue;
      }

      cur_line_len += word_len;

      if (i == argc - 1)
        PrintPaddedBreak(longest - cur_line_len);

      continue;
    }

    // Create a line break if the current line is nonempty.
    if (cur_line_len > 0) {
      PrintPaddedBreak(longest - cur_line_len);
      printf("| ");
    }

    // If the word itself is too long, then we need to break it apart.
    // Otherwise, we print the current word and move on.
    if (word_len > MAX_WIDTH) {
      char* str = argv[i];
      int processed = 0;
      for (int j = 0; j <= word_len / MAX_WIDTH; j++) {
        int len = MIN(MAX_WIDTH, strlen(str));
        printf("%.*s", len, str);
        PrintPaddedBreak(longest - len);
        str += len;
        processed += len;
        if (processed >= word_len - 1) break;
        printf("| ");
      }

      cur_line_len = 0;
    } else {
      printf("%s ", argv[i]);
      cur_line_len = word_len;
      if (word_len == MAX_WIDTH || i == argc - 1) {
        PrintPaddedBreak(longest - cur_line_len);
      }
    }
  }
}

int main(int argc, char** argv) {
	int bubble_width;
  if (argc == 1) {
    printf("Usage: cowsay [message]\n");
    return 1;
  }

  // No wordwrap because I'm too lazy.
  //int bubble_width = LongestLineLength(argc - 1, argv + 1) + 1;
  bubble_width = LongestLineLength(argc - 1, argv + 1) + 1;

  printf(" _");
  for (int i = 0; i < bubble_width; i++)
    printf("_");
  printf(" \n");

  PrintMessage(argc - 1, argv + 1, bubble_width - 1);

  printf(" -");
  for (int i = 0; i < bubble_width; i++)
    printf("-");
  printf(" \n");

  printf("     \\  ^__^\n");
  printf("      \\ (oo)\\_____\n");
  printf("        (__)\\     )\\/\\\n");
  printf("           ||----w |\n");
  printf("           ||     ||\n");

  return 0;
}
