//=-- PPErrors.cpp - Error Hit analysis Page Plugin... -----------------------=
//
//  PLUGIN DESCRIPTION:
//    This plugin in intended to be used to track the errors that happen to a 
//  web site.  
//
//  PLUGIN AUTHOR:
//    Chris Lattner, Author of Magicstats  (sabre@magic.hurrah.com)
//
//  PLUGIN HOMEPAGE:
//     http://www.magicstats.com/
//
//  PLUGIN VERSION / COMPATIBILITY:
//     TestPlugin v1.0 / MagicStats 2.0+
//
//=---------------------------------------------------------------------------=
//  This file is copyright (c) 1997-2000 Chris Lattner
//=---------------------------------------------------------------------------=

#include "PagePlugin.h"
#include "DataGraph.h"
#include "SerializeEx.h"
#include "Table.h"
#include "VarTable.h"

class PPErrors : public PluginTemplate<PagePlugin,PPErrors> {
public:
  inline static unsigned int GetCurrentVersion() {
    return 100;                       // Version 1.00
  } 

  inline static const char *GetPluginName() {
    return "PageErrors";
  }

  PPErrors(int &CE) { 
    CE = 0;
    Flags = FAutoFilter;
    ResetState();
  }

  // The full name consists of all of the data settings that alter the data 
  // that is kept track of and stored.
  void GetFullName(VarTable &Params, String &fullName, int updateFreq) {
  String Filt;
  if (Params["Filter"] != 0) {
    Filt = Params["Filter"]->GetStringValue();
  } else {
    Filt = DefFilter.ToParamStr();
  }

    fullName = String::IntToStr(updateFreq) + Name + Filt;
  }

  void ProcessAccess(AccessFormatPlugin &A) {
    if (A.GetStatusCode() > 200) {
      CountTable[String::IntToStr(A.GetStatusCode())+"\t"+A.GetURL()]++;
    }
  }
  
  void OutputHTML(ostream &O, VarTable &Params) {
    DataGraph Data(Params);
    typedef DataPair<String,int> Pair;
    LinkedList<Pair> List;
    
    LinkedList<String> RowLabels, Pages, 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);
    
    // Go through the list and convert URL's to links...
    LinkedList<Pair>::Iterator I = List.GetIterator();
    while (I) {
      String Code, URL;
      Code = URL = I->P;
      int i = Code.strchr('\t');
      Code.Left(i);
      URL.Right(URL.Length()-i-1);
      I->P = Code + " -  <a href='" + URL + "'>" + URL + "</a>";
      I++;
    }
    
    Data.SetRowLabelFormat(1);     // Increasing integer labels
    Data.SetRowLabels(RowLabels);
    Data.AddColumn(Pages);
    Data.AddColumn(Count);
    
    RowLabels.AddToTail("#");
    Pages.AddToTail("Error Code - Web Page URL:");
    Count.AddToTail("Hits:");
    
    I = List.GetIterator();
    while (I) {
      Pages.AddToTail(I->P);
      Count.AddToTail(String::IntToStr(I->S));
      I++;
    }
    
    Data.WriteHTML(O);
  }

  void ResetState() {
    CountTable.Clear();        // Free all of the data in the linked list...
    CountTable.SetDefault(0);
  }
  
  void LoadState(Serialize &I) {
    unsigned int Version = 0;

    ResetState();
    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 SaveState(Serialize &O) {
    O << GetCurrentVersion();  // Serialize the Version number
    O << CountTable;
  }

private :
  Table<String, int> CountTable;
};

INIT_PLUGIN(PPErrors);
