//=-- ServerSettings.cpp - Manages global server settings --------------------=
//
//  This class extends the ConfigFile class.  It provides easy access to the
//  fields that are present in the Server Configuration file.  Because the
//  Server Configuration file is not required for use of MagicStats, it also
//  cancels the printing of error messages.
//
//=---------------------------------------------------------------------------=
//  This file is copyright (c) 1997-1998 Chris Lattner
//=---------------------------------------------------------------------------=

#include "ServerSettings.h"
#include "ResourceManager.h"
#include "MSFilename.h"
#include "Options.h"
#include "ConfigRep.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;
}

int ServerSettings::Load(const MSFilename &Filename) {
  Table<CSString,VTExp*> Vars;

  ConfigFileSection *CFile = LoadConfigFile(Filename);
  if (CFile == 0) return -1;

  if (MSOptions::Debug) {
    cout << "*** Printing Server Settings ServerSettings.cpp:" 
         << __LINE__ << endl;
    CFile->Print(Vars);
  }

  LinkedList<CFileSection> ConfFile = CFile->EvaluateFile(Vars);

  cout << "Loaded ConfigFile " << ConfFile << endl;

  LLLink<CFileSection> *Section = ConfFile.GetHead();

  while (Section) {
    if (Section->Data.GetSectionName() == CSString("ServerSettings"))
      ProcessServerSettings(Section->Data.GetStatements());
    else if (Section->Data.GetSectionName() == CSString("UserSettings"))
      ProcessUserSettings(Section->Data.GetStatements());
    else if (Section->Data.GetSectionName() == CSString("SecuritySettings"))
      ProcessSecuritySettings(Section->Data.GetStatements());
    else 
      cout << "Error parsing Server Configuration File: Unrecognized "
           << "section '" << Section->Data.GetSectionName() << "'!\n";

    Section = Section->GetNext();
  }

  return 0;
}

static void AddResourcesList(VTListExp *List, int ResType) {
  int i, Length = List->GetNumElements();

  for (i = 0; i < Length; i++) {
    VTExp *Element = List->GetListElement(i);
    if (Element && Element->GetExpType() == VTExp::ListTy) {
      // Recursively add resources...
      AddResourcesList((VTListExp*)Element, ResType);
    } else {    // Must be a pair of values...
      VTExp *Element2 = List->GetListElement(i+1);
      if (Element == 0 || Element2 == 0 || 
          Element2->GetExpType() != VTExp::StringTy) {
        cout << "'Resources' list expected a Pair of values: '"
             << Element << "', '" << Element2 << "'!\n";
      } else {
        if (ResourceManager::AddResourceLocation(Element->GetStringValue(), 
                                                 Element2->GetStringValue(), 
                                                 0)) {
          cout << "Error adding resource directory '"  
               << Element->GetStringValue()
               << "' from server configuration file!  Ignoring path.\n";
        }
        i++;   // Advance past second read value...
      }
    }
  }
}


void ServerSettings::ProcessServerSettings(VarTable &Keys) {
  typedef MSOptions O;

  O::AccessLogType     = GetSKeyValue(Keys, "AccessLogType", O::AccessLogType);

  VTExp *Value = Keys["AccessLog"];
  if (Value) {
    if (MSOptions::AccessLog)
      MSOptions::AccessLog->UnRef();  // Release default value...
    MSOptions::AccessLog = Value->AddRef();
  }

  if (Keys.InTable("ServerResources")) {
    VTExp *Res = Keys["ServerResources"];

    if (Res->GetExpType() != VTExp::ListTy) {
      cout << "'ServerResources' value must be a list, in server config file!\n";
    } else {
      AddResourcesList((VTListExp*)Res, 1);
    }
  }
}

void ServerSettings::ProcessUserSettings(VarTable &Keys) {
  if (Keys.InTable("UserResources")) {
    VTExp *Res = Keys["UserResources"];

    if (Res->GetExpType() != VTExp::ListTy) {
      cout << "'UserResources' value must be a list, in server config file!\n";
    } else {
      AddResourcesList((VTListExp*)Res, 0);
    }
  }
}

void ServerSettings::ProcessSecuritySettings(VarTable &Keys) {
  typedef MSOptions O;
  int &AllowUserResources = ResourceManager::AllowUserResources;

  AllowUserResources       = GetIKeyValue(Keys, "AllowUserThemes", AllowUserResources);
  O::MinimumRefreshDelay   = GetIKeyValue(Keys, "MinimumRefreshDelay", O::MinimumRefreshDelay);
  O::AllowAlternateLogs    = GetIKeyValue(Keys, "AllowAlternateLogs" , O::AllowAlternateLogs);
  O::AllowWebUserAdmin     = GetIKeyValue(Keys, "AllowWebUserAdmin"  , O::AllowWebUserAdmin);
  O::AllowWebServerAdmin   = GetIKeyValue(Keys, "AllowWebServerAdmin", O::AllowWebServerAdmin);
  O::AllowDynaStats        = GetIKeyValue(Keys, "AllowDynaStats"     , O::AllowDynaStats);
}
