/*
 * Copyright 2011 Steven Gribble
 *
 *  This file is the solution to an exercise problem posed during
 *  one of the UW CSE 333 lectures (333exercises).
 *
 *  333exercises is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  333exercises is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with 333exercises.  If not, see <http://www.gnu.org/licenses/>.
 */

// Lecture 7 livecoding example.

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <readline/readline.h>
#include <readline/history.h>

#include "ll.h"
#include "readlinefromfile.h"
#include "graphops.h"

static void usage(void);
static void SlurpScientists(FILE *f);
static void PrintGraph(FILE *f, char *scientist);

static void SlurpScientists(FILE *f) {
  int count = 1;
  printf("slurping in and building collaboration graph...\n");

  // Slurp in the graph file, a line at a time
  while (1) {
    char *s1 = NULL, *s2 = NULL, *s3 = NULL;
    int res;

    // read the "A" field
    res = ReadNextLine(f, &s1);
    if (res == 0)
      break;

    // read the "B" field
    res = ReadNextLine(f, &s2);
    assert(res != 0);

    // read the empty field separating the edges
    res = ReadNextLine(f, &s3);
    assert(res != 0);

    // add in A--B and B--A
    AddCollaboration(s1, s2);
    AddCollaboration(s2, s1);
    free(s1);
    free(s2);
    free(s3);

    // see if we should print status
    count++;
    if (count % 1000 == 0) {
      printf("read in %d of 175,691 edges...\n", count);
    }
  }
}

// Prints out the "friends + friends-of-friends" two
// hop graph for the given scientist.
static void PrintGraph(FILE *f, char *scientist) {
  // Graph the collaborator list for the scientist.
  Node *clist = GetCollaboratorList(scientist);
  if (clist == NULL) {
    usage();
  }

  // Since clist is not NULL, this scientist has at
  // least one collaborator.  So, we're ready to start
  // generating the graph.

  // print out the graph header
  fprintf(f, "graph sciencegraph {\n");
  fprintf(f, "  overlap=scale\n");

  // iterate through the collaborators
  while(clist != NULL) {
    char *cname = clist->element;

    // print out the direct collaboration edge
    fprintf(f, "  %s -- %s\n", scientist, cname);

    // print out the friend-of-friends edges
    if (1) {
      Node *cclist = GetCollaboratorList(cname);

      while (cclist != NULL) {
        char *c_of_c_name = (char *) cclist->element;
        // For each collaborator-of-collaborator, we test
        // to see if that c-of-c is also a c-of-scientist.
        // If so, we need to be careful to print out
        // that c-of-c edge only once, so we'll print it out
        // conditionally ordered by name.
        if (TestIfCollaborator(scientist, c_of_c_name)) {
          if (strcmp(cname, c_of_c_name) < 0) {
            fprintf(f, "  %s -- %s\n", cname, c_of_c_name);
          }
        } else {
          fprintf(f, "  %s -- %s\n", cname, c_of_c_name);
        }
        cclist = cclist->next;
      }
    }
    clist = clist->next;
  }

  // print out graph trailer
  fprintf(f, "}\n");
}

static void usage(void) {
  fprintf(stderr, "Usage: ./gconsole collaboratorlist\n");
  exit(-1);
}

int main(int argc, char **argv) {
  FILE *f;
  if (argc != 2)
    usage();

  f = fopen(argv[1], "r");
  if (f == NULL)
    usage();
  SlurpScientists(f);
  fclose(f);

  while(1) {
    // Prompt the user and get input text, using Linux's readline()
    // helper function.
    char *sname = readline("scientist name: ");
    if (sname == NULL)
      exit(0);

    // Make sure the scientist provided to us is in the graph.
    if (GetCollaboratorList(sname) == NULL) {
      fprintf(stderr, "unknown scientist '%s'\n", sname);
    } else {
      // Open up output file for neato graph.
      char outnamebuf[256];
      assert(strlen(sname) < 250);
      snprintf(outnamebuf, 256, "%s.neato", sname);
      f = fopen(outnamebuf, "w");
      if (f == NULL) {
        fprintf(stderr, "couldn't open output file '%s'\n", outnamebuf);
      } else {
        PrintGraph(f, sname);
        fclose(f);
      }
    }
    free(sname);
  }
  return 0;
}