//=-- DataGraph.cpp - Interface to graph applet ------------------------------=
//
//  This class 
//
//=---------------------------------------------------------------------------=
//  This file is copyright (c) 1997-2000 Chris Lattner
//=---------------------------------------------------------------------------=

#include <limits.h>
#include "DataGraph.h"
#include "Table.h"
#include "Options.h"
#include "VarTable.h"

static int GetIKeyValue(VarTable &T, const CSString &K, int Default) {
  if (T.InTable(K))
    return T[K]->GetStringValue().atoi();
  return Default;
}

static String GetSKeyValue(VarTable &T, const CSString &K, 
                           const String &Default) {
  if (T.InTable(K))
    return T[K]->GetStringValue();
  return Default;
}

void DataGraph::LoadParams(VarTable &Params) {
  Width                = GetIKeyValue(Params, "Graph.Java.GraphWidth"     , 500); 
  Height               = GetIKeyValue(Params, "Graph.Java.GraphHeight"    , 300);
  BarColor             = GetSKeyValue(Params, "Graph.Java.BarColor"       , "#0000FF");
  BarEndColor          = GetSKeyValue(Params, "Graph.Java.BarEndColor"    , "#0000FF");
  BGColor              = GetSKeyValue(Params, "Graph.BGColor"             , "#FFFFFF");
  TableColumnHeadColor = GetSKeyValue(Params, "Graph.Table.ColumnHeadColor", "#FFFF00");
  LinkToURL            =  Params["Graph.Table.LinkTo"];
  
  BarStyle             = GetIKeyValue(Params, "Graph.Java.BarStyle"       , 2);
  BarCenter            = GetIKeyValue(Params, "Graph.Java.BarCenter"      , 128);
  
  ASCIIMaxBarLength    = GetIKeyValue(Params, "Graph.ASCII.MaxBarLength"  , 70);
  ImageMaxBarLength    = GetIKeyValue(Params, "Graph.Image.MaxBarLength"  , 500);
  MaxListLength        = GetIKeyValue(Params, "Graph.MaxListLength"       , -1);
  
  ImageBarImage        = GetSKeyValue(Params, "Graph.Image.BarImage"      , MSOptions::GetBuiltInPluginResURL()+"/Yellow.gif");
  Format               = GetSKeyValue(Params, "Graph.Format"              , "GRAPH");
}

int DataGraph::WriteHTML(ostream &O) {
  int i = 0, j;
  int NumColumns = Columns.GetLength();
  LLLink<String> *RowLabel = (RowLabels != 0) ? RowLabels->GetHead() : 0;
  LLLink<String> **Temp = new LLLink<String> *[NumColumns];
  LLLink<StrListPtr> *Column;
  String Bar;
  
  Column = Columns.GetHead();
  for (i = 0; i < NumColumns; i++) {
    Temp[i] = ((const LinkedList<String> *)Column->Data)->GetHead();
    Column = Column->GetNext();
  }
  
  if (Format.iCompare("TABLE")) {      // If it does not say table, then do a graph...
    O << "<APPLET CODE=StatsGraph.class width=" << Width 
      << " height=" << Height << endl
      << " CODEBASE='" << MSOptions::GetBuiltInPluginResURL() << "'";
    
    O << "><PARAM NAME=BGColor VALUE="     << BGColor           << endl;
    O << "><PARAM NAME=BarColor VALUE="    << BarColor          << endl;
    O << "><PARAM NAME=EndBarColor VALUE=" << BarEndColor       << endl;
    O << "><PARAM NAME=BarStyle VALUE="    << BarStyle          << endl;
    O << "><PARAM NAME=BarCenter VALUE="   << BarCenter         << endl;
    O << "><PARAM NAME=LabelForm VALUE="   << RowLabelFormat    << endl;
    O << "><TABLE border=0 cellspacing=0 cellpadding=0><TR><TD" << endl;
    
    // Skip the first row label...
    if (RowLabel != 0) RowLabel = RowLabel->GetNext();
    
    int Max = INT_MIN;
    for (i = 1; i < NumColumns; i++) {
      Temp[i] = Temp[i]->GetNext();
      if (Temp[i] != 0) {
        LLLink<String> *Temp2 = Temp[i];
        while (Temp2 != 0) {
          if ((j = Temp2->Data.atoi()) > Max)
            Max = j;
          Temp2 = Temp2->GetNext();
        }
      }
    }
    
    i = 0;
    if (Max == 0) Max = 1;
    
    // Spit out the graph
    while ((Temp[1] != 0) && (i != MaxListLength)) {
      i++;
      
      Bar.Fill('*', ASCIIMaxBarLength * Temp[1]->Data.atoi() / Max);
      
      O << "><PARAM NAME=Data" << i << " VALUE=" << Temp[1]->Data
        << "><br><IMG SRC=\"" << ImageBarImage << '"';
      O << " ALT=\"";
      OutputRowLabel(O, i, RowLabel);
      
      O << "  " << Bar << "\" HEIGHT=10 BORDER=1 "
        << "WIDTH=" << ImageMaxBarLength * Temp[1]->Data.atoi() / Max << endl;
      
      for (j = 0; j < NumColumns; j++) {
        if (Temp[j] != 0) {
          Temp[j] = Temp[j]->GetNext();
        }
      }
    }
    
    O << "><PARAM NAME=NumDataPoints VALUE=" << i << endl;
    O << "></TD></TR></TABLE></APPLET>" << endl;
    
  } else { // Print out the table...
    
    O << "<TABLE width=100% border=0 cellspacing=0 cellpadding=0><TR>" << endl
      << "</TR><TR><TD VALIGN=TOP WIDTH=50%><table width=100% border=1><tr>" << endl
      
      << "<td BGColor=" << TableColumnHeadColor 
      << "><FONT SIZE=4> ";
    
    if (RowLabel != 0) {
      O << RowLabel->Data;
      RowLabel = RowLabel->GetNext();
    }
    
    O << "</FONT></TD>" << endl;
    
    for (j = 0; j < NumColumns; j++) {
      O << "<TD BGColor=" << TableColumnHeadColor 
        << "><FONT SIZE=4>" << Temp[j]->Data << "</FONT></TD>" << endl;
      Temp[j] = Temp[j]->GetNext();
    }
    
    O << "</TR>";

    String LinkToURLStr;
    if (LinkToURL) LinkToURLStr = LinkToURL->GetStringValue();
    
    i = 0;
    while ((Temp[1] != 0) && (i != MaxListLength)) {
      i++;
      
      O << "<TR><TD>";
      OutputRowLabel(O, i, RowLabel);
      
      for (j = 0; j < NumColumns; j++) {
        O << "</TD><TD>";
        
        if (Temp[j] != 0) {
          if (LinkToURL) 
            O << "<a href='" << LinkToURLStr << Temp[j]->Data << "'>";

          O << Temp[j]->Data;

          if (LinkToURL) 
            O << "</a>";

          Temp[j] = Temp[j]->GetNext();
        }
      }
      
      O << "</TD></TR>" << endl;
    }
    
    O << "</TR></Table><p>"
      << "</TD></TR></TABLE><p><p>";
  }

  delete Temp;
  return 0;
}

void DataGraph::OutputRowLabel(ostream &o, int i, LLLink<String> *&RowLabel) {
  if (RowLabel != 0) {
    o << RowLabel->Data;
    RowLabel = RowLabel->GetNext();
  } else {
    
    switch (RowLabelFormat) {
    case 1:
      o << i << ".";
      break;
    case 2:
      o << ((i-1) % 12) + 1 << ":00";
      break;
    }
  }
}
