/******************************************************************
  
  Module:  tuning.cpp
  
  Author: Sean Craig
  
  Copyright 2005 Sony Online Entertainment.  All rights reserved.
  
*******************************************************************/

//-------------------------------------------------------- Includes
#include "tuning.h"
#include "tinyxml.h"
#include "SyMath.h"
#include "SyStr.h"
//---------------------------------------------- Class Declarations
class cTuningVar
{
public:
  cTuningVar(const char *name): mName(name){};
  virtual ~cTuningVar(){};

  virtual void Set(const char *value)=0;
  const char *GetName(){return mName;};
protected:
  const char *      mName;
};


class cTuningVar_Float : public cTuningVar
{
public:
  cTuningVar_Float(float *value,const char *name) : cTuningVar(name), mValue(value){};

  virtual void Set(const char *value){*mValue = (float)atof(value);}

protected:
  float     *mValue;
};

class cTuningVar_Int : public cTuningVar
{
public:
  cTuningVar_Int(int *value,const char *name) : cTuningVar(name), mValue(value){};

  virtual void Set(const char *value){*mValue = atoi(value);}

protected:
  int     *mValue;
};

class cTuningVar_Angle : public cTuningVar
{
public:
  cTuningVar_Angle(float *value,const char *name) : cTuningVar(name), mValue(value){};

  virtual void Set(const char *value){*mValue = SY_DEG_TO_RAD(atoi(value));}

protected:
  float     *mValue;
};
//----------------------------------------- Global Variable Definitions

cTuningSys gTuningSys; // only one set of tuning variables for all games

//----------------------------------------- Functions Declarations
//------------------------------------ Member Functions Definitions

//------------------------------------ cTuningSys
cTuningSys::~cTuningSys()
{
  Init();
}

void 
cTuningSys::Init()// call before values are added;
{
  int curIndex;
  for (curIndex = mVars.Begin();curIndex != mVars.End();curIndex = mVars.Next(curIndex))
  {
    delete mVars(curIndex);
  }

  mVars.Clear();
}

bool
cTuningSys::LoadValues()
{
  const char *FILENAME = "data/tuning.xml";
	TiXmlDocument doc( FILENAME );
	bool loadOkay = doc.LoadFile();

	if ( !loadOkay )
	{
    SyAssertf(0, "Unable to load tuning XML file: %s",FILENAME);
    return false;
	}
  
	TiXmlNode* node = 0;

  node = doc.FirstChild( "Settings" );
  SyAssert(node);         

#if 0
  int curIndex;
  for (curIndex = mVars.Begin();curIndex != mVars.End();curIndex = mVars.Next(curIndex))
  {
    TuningVar *cur = mVars(curIndex);
    TiXmlNode* data_node = node->FirstChild(cur->GetName());
    if (data_node != NULL)
    {
      cur->Set(data_node->FirstChild()->Value());
    }
  }
#endif
  node = node->FirstChild();
  while (node != NULL)
  {
    const char *name = node->Value();
    int curIndex;
    cTuningVar *cur = NULL;
    for (curIndex = mVars.Begin();curIndex != mVars.End();curIndex = mVars.Next(curIndex))
    {
      if (SyStr::Stricmp(mVars(curIndex)->GetName(),name)==0)
      {
        cur = mVars(curIndex);
        break;
      }
    }
    if (cur == NULL)
    {
      SyAssertf(0,"Unknown tuning variable '%s'",name);
    }
    else
    {
      cur->Set(node->FirstChild()->Value());
    }
    node = node->NextSibling();
  }
  return true;
}


bool 
cTuningSys::AddFloat(float *var, const char *name)
{
  int curIndex;
  for (curIndex = mVars.Begin();curIndex != mVars.End();curIndex = mVars.Next(curIndex))
  {
    if (SyStr::Stricmp(mVars(curIndex)->GetName(),name)==0)
    {
      SyAssertf(0,"Duplicate tuning variable added");
      return false; // dupe...
    }
  }
  mVars.Add(new cTuningVar_Float(var,name));
  return true;
}

bool 
cTuningSys::AddInt(int *var, const char *name)
{
  int curIndex;
  for (curIndex = mVars.Begin();curIndex != mVars.End();curIndex = mVars.Next(curIndex))
  {
    if (SyStr::Stricmp(mVars(curIndex)->GetName(),name)==0)
    {
      SyAssertf(0,"Duplicate tuning variable added");
      return false; // dupe...
    }
  }
  mVars.Add(new cTuningVar_Int(var,name));

  return true;
}


bool 
cTuningSys::AddAngle(float *var, const char *name)
{
  int curIndex;
  for (curIndex = mVars.Begin();curIndex != mVars.End();curIndex = mVars.Next(curIndex))
  {
    if (SyStr::Stricmp(mVars(curIndex)->GetName(),name)==0)
    {
      SyAssertf(0,"Duplicate tuning variable added");
      return false; // dupe...
    }
  }
  mVars.Add(new cTuningVar_Angle(var,name));

  return true;
}
// EOF
