//=-- CountPlugin.cpp - Implements the Count plugin ----------------*- C++ -*-=
//
//  This class is used to implement the "most frequent" tables and graphs.  It
//  can be parameterized to display the most frequent anything: hosts, pages,
//  referrers, whatever!
//
//=---------------------------------------------------------------------------=
//  This file is copyright (c) 1997-2000 Chris Lattner
//=---------------------------------------------------------------------------=

#include "DataGraph.h"
#include "CountPlugin.h"
#include "SerializeEx.h"
#include "Options.h"

INIT_PLUGIN(CountPlugin);

CountPlugin::CountPlugin(int &CreateError) {
  Flags = FAutoFilter | FIgnoreErrors;
  ResetState();
  CreateError = 0;
  FieldToCount = -1;
}

void CountPlugin::LoadSettings(VarTable *Params) {
  // Load the field to process...
  if (Params->InTable("Field")) {
    const String &FieldStr = (*Params)["Field"]->GetStringValue();
    FieldToCount = AccessFormatPlugin::GetFieldID(FieldStr);
  }

  if (FieldToCount == -1) FieldToCount = AccessFormatPlugin::FEHost;
}


void CountPlugin::GetFullName(VarTable &Params, String &fullName, 
                              int updateFreq) {
  String Filt;
  int Field = FieldToCount;

  if (Params.InTable("Field"))
    Field = AccessFormatPlugin::GetFieldID(Params["Field"]->GetStringValue());

  if (Params["Filter"] != 0) {
    Filt = Params["Filter"]->GetStringValue();
  } else {
    Filt = DefFilter.ToParamStr();
  }

  if (Field == -1) Field = AccessFormatPlugin::FEHost;
  fullName = String::IntToStr(updateFreq) + "\t" 
    + String::IntToStr(Field) + Name +  "\t" + Filt;
}

void CountPlugin::ProcessAccess(AccessFormatPlugin &A) {
  String Val = A.GetField(FieldToCount);
  if (Val.Length() > 0)
    CountTable[Val]++;   // Ignore empty strings!
}

void CountPlugin::ResetState() {
  CountTable.Clear();        // Free all of the data in the table...
  CountTable.SetDefault(0);
}

void CountPlugin::LoadState(Serialize &I) {
  unsigned int Version = 0;
  String Host;

  I >> Version;

  // Check version number...
  switch (Version) {
  case 100:                  // Version 1.00
    I >> CountTable;
    break;
    
  default:
    cout << "Serialized " << Name << " Page plugin is of a version that cannot "
         << "be deserialized\nwith this version of the plugin.  Reseting state.\n";
    break;
  }
}

void CountPlugin::SaveState(Serialize &O) {
  O << GetCurrentVersion();  // Serialize the Version number
  O << CountTable;
}

void CountPlugin::OutputHTML(ostream &O, VarTable &Params) {
  DataGraph Data(Params);
  typedef DataPair<String,int> Pair;
  LinkedList<Pair> List;

  LinkedList<String> RowLabels, Hosts, Count;

  // Copy the data from the table into the linked list...
  CountTable.ConvertToList(List);

  // Sort the data list by the number of hits.
  List.Sort(&Pair::SortBySecondary);

  Data.SetRowLabelFormat(1);     // Increasing integer labels
  Data.SetRowLabels(RowLabels);
  Data.AddColumn(Hosts);
  Data.AddColumn(Count);

  // Set the defaults...
  RowLabels.AddToTail("#");
  Hosts.AddToTail("Most Common:");
  Count.AddToTail("Hits:");


  if (Params.InTable("Graph.Table.Headers")) {
    VTExp *HExp = Params["Graph.Table.Headers"];
    if (HExp->GetExpType() != VTExp::ListTy) {
      if (MSOptions::Verbose)
        cout << "CountPlugin expects a list for the 'Graph.Table.Headers' "
             << "parameter!\n" << "I received: " << HExp << endl;
    } else {
      VTListExp *Vals = (VTListExp*)HExp;
      if ((HExp = Vals->GetListElement(0))) 
        RowLabels.ClearList(); RowLabels.AddToTail(HExp->GetStringValue());
      if ((HExp = Vals->GetListElement(1))) 
        Hosts.ClearList(); Hosts.AddToTail(HExp->GetStringValue());
      if ((HExp = Vals->GetListElement(2))) 
        Count.ClearList(); Count.AddToTail(HExp->GetStringValue());
    }
  }

  LinkedList<Pair>::Iterator I = List.GetIterator();
  while (I) {
    Hosts.AddToTail(I->P);
    Count.AddToTail(String::IntToStr(I->S));
    I++;
  }

  Data.WriteHTML(O);
}
