/****************************************************************************
 * Copyright (c) 1992-2026 MAK Technologies, Inc
 * All rights reserved.
 ****************************************************************************/

//! \file multiConfigVariable.inl
//! \brief Contains the DtMultiConfigVariable class definition.
//! \ingroup vl

#include <mtl/multiConfigVariable.h>

#pragma warning (disable : 4996 ) // strcpy warning

template <typename T>
DtMultiConfigVariable<T>::DtMultiConfigVariable( DtVariableGroup* group,
      const DtString& theVarName, const DtString& itemName,
      const DtString& description /* = "" */,
      DtVariableScope aScope /* DtBaseConfigVariable::DtScopeBoth */,
      bool required /* = false */, const DtString& theVarShortcut /* = "" */ )
   : DtBaseConfigVariable( group, aScope, description )
   , myName( theVarName )
   , myItemName( itemName )
   , myShortcut( theVarShortcut )
   , myRequiredFlag( required )
   , myGroup( group )
   , myValues()
{
   char* nonConstMyName = const_cast<char*>( myName.c_str() );
   char* shortCutPtr = strchr( nonConstMyName, '&' );
   if ( shortCutPtr )
   {
      char sc[2];
      sc[1] = '\0';
      sc[0] = shortCutPtr[1];
      DtString dup( shortCutPtr + 1 );
      strcpy( shortCutPtr,dup.c_str() );
      myShortcut = sc;
   }
}

template <typename T>
DtMultiConfigVariable<T>::DtMultiConfigVariable( DtVariableGroup& group,
      const DtString& aName, const DtString& itemName,
      const DtString& aDescription /* = "" */,
      DtVariableScope aScope /* = DtBaseConfigVariable::DtScopeBoth */,
      bool isRequired /* = false */, const DtString& aShortcut /* = "" */ )
   : DtBaseConfigVariable( &group, aScope, aDescription )
   , myName( aName )
   , myItemName( itemName )
   , myShortcut( aShortcut )
   , myRequiredFlag( isRequired )
   , myGroup( &group )
   , myValues()
{
   char* nonConstMyName = const_cast<char*>( myName.c_str() );
   char* shortCutPtr = strchr( nonConstMyName, '&' );
   if ( shortCutPtr )
   {
      char sc[2];
      sc[1] = '\0';
      sc[0] = shortCutPtr[1];
      DtString dup( shortCutPtr + 1 );
      strcpy( shortCutPtr, dup.c_str() );
      myShortcut = sc;
   }
}

template <typename T>
DtMultiConfigVariable<T>::DtMultiConfigVariable( DtVariableGroup* group,
      const DtMultiConfigVariable<T>& orig )
   : DtBaseConfigVariable( group, orig.myScope, orig.myDescription )
   , myName( orig.myName )
   , myItemName( orig.myItemName )
   , myShortcut( orig.myShortcut )
   , myRequiredFlag( orig.myRequiredFlag )
   , myGroup( group )
   , myValues( orig.myValues )
{
   mySetFlag = orig.mySetFlag;
   if ( orig.myArg )
   {
      myArg = new DtCmdLine::MultiArg<ArgType>( myShortcut.c_str(),
         myName.c_str(), myDescription.c_str(), myRequiredFlag,
         DtVarType<T>::argNameOfType().c_str() );
   }
}

template <typename T>
DtMultiConfigVariable<T>::DtMultiConfigVariable( DtVariableGroup& group,
      const DtMultiConfigVariable<T>& orig )
   : DtBaseConfigVariable( &group, orig.myScope, orig.myDescription )
   , myName( orig.myName )
   , myItemName( orig.myItemName )
   , myShortcut( orig.myShortcut )
   , myRequiredFlag( orig.myRequiredFlag )
   , myGroup( &group )
   , myValues( orig.myValues )
{
   mySetFlag = orig.mySetFlag;
   if ( orig.myArg )
   {
      myArg = new DtCmdLine::MultiArg<ArgType>( myShortcut.c_str(),
         myName.c_str(), myDescription.c_str(), myRequiredFlag,
         DtVarType<T>::argNameOfType().c_str() );
   }
}

template <typename T>
DtMultiConfigVariable<T>::~DtMultiConfigVariable()
{
}

template <typename T>
DtMultiConfigVariable<T>& DtMultiConfigVariable<T>::operator = (
   const DtMultiConfigVariable<T>& other )
{
   // Prevent assignment to self.
   if ( this == &other )
   {
      return *this;
   }

   DtBaseConfigVariable::operator = ( other );

   myName = other.myName;
   myItemName = other.myItemName;
   myShortcut = other.myShortcut;
   myRequiredFlag = other.myRequiredFlag;
   myValues = other.myValues;

   if ( other.myArg )
   {
      myArg = new DtCmdLine::MultiArg<ArgType>( myShortcut.c_str(),
         myName.c_str(), myDescription.c_str(), myRequiredFlag,
         DtVarType<T>::argNameOfType().c_str() );
   }

   return *this;
}

template <typename T>
void DtMultiConfigVariable<T>::getEnvironmentSchemaType(DtEnvironment env,
   TypeSet& usedTypes) const
{
// TODO:    Implement this

//    if(usedTypes.find(type()) == usedTypes.end())
//    {
//       usedTypes.insert(type());
//       DtEnvValueSP type = DtVarType<T>::createSchemaType(env);
//       DtEnvironment tmp(type);
//       if(!myRequiredFlag)
//       {
//          tmp.addAttribute("minOccurs","0");
//       }      
//    }  
}

template <typename T>
DtEnvValueSP DtMultiConfigVariable<T>::getEnvironmentValue(DtEnvironment env)
{      
   if (!description().isEmpty())
   {
      env.addComment(description());
   }
   // First lets add the list name
   DtEnvValueSP listObject = env.addObject(myName);
   DtEnvironment listEnv = DtEnvironment(listObject);

   for (unsigned int index = 0; index < myValues.size(); ++index )
   {
      DtEnvValueSP object = listEnv.addObject(myItemName);
      DtVarType<T>::convertToEnvironmentValue(DtEnvironment(object), myValues[index]);
   }
   return listObject;
}

template <typename T>
DtString DtMultiConfigVariable<T>::type() const
{
   return "list";//DtVarType<T>::nativeNameOfType();
}

template <typename T>
void DtMultiConfigVariable<T>::updateFromEnvironment(DtEnvironment env)
{
   // Move environment root to group
   if (myGroup)
   {
      env.setRoot(myGroup->getGroupValue(env));
   }

   std::list<DtEnvValueSP> outerList;
   env.getObjectsByName(myName, outerList);

   if (outerList.size() == 1)
   {
      env.setRoot(outerList.front());

      // Now get all the items
      std::list<DtEnvValueSP> innerList;
      env.getObjectsByName(myItemName, innerList);

      std::list<DtEnvValueSP>::iterator curIter = innerList.begin();
      std::list<DtEnvValueSP>::iterator endIter = innerList.end();

      clearValues();
      for (;curIter != endIter; ++curIter)
      {
         DtEnvObject* obj = DtEnvObject::castToObject(*curIter);
         if (obj)
         {
            T convertedVal = DtVarType<T>::convertFromEnvironmentValue(DtEnvironment(*curIter));
            myValues.push_back(convertedVal);
         }
      }
   }
}

template <typename T>
void DtMultiConfigVariable<T>::updateFromCommandLineArg()
{
   const std::vector<ArgType>& values = ((DtCmdLine::MultiArg<ArgType>*)myArg)->getValue();
   if (values.size() > 0)
   {
      myValues.clear();
      for (unsigned int index = 0; index < values.size(); ++index)
      {
         myValues.push_back(DtVarType<T>::convertFromArgType(values[index]));
      }
      mySetFlag = true;
   }
}

template <typename T>
void DtMultiConfigVariable<T>::getCommandLineArg(DtCmdLine::CmdLine& cmdLine)
{
   // TODO:    Implement this
   if (inCommandLine())
   {
      if(!myArg)
      {
         myArg = new DtCmdLine::MultiArg< ArgType >(
            myShortcut.c_str(),
            myName.c_str(),
            myDescription.c_str(), 
            myRequiredFlag, 
            DtVarType<T>::argNameOfType().c_str());
      }
      cmdLine.add(myArg);
   }
}

template <typename T>
bool DtMultiConfigVariable<T>::isRequired() const
{
   return myRequiredFlag;
}

template <typename T>
const DtString& DtMultiConfigVariable<T>::name() const
{
   return myName;
}

template <typename T>
const DtString& DtMultiConfigVariable<T>::shortcut() const
{
   return myShortcut;
}

template <typename T>
const std::vector<T>& DtMultiConfigVariable<T>::values() const
{
   return myValues;
}

template <typename T>
void DtMultiConfigVariable<T>::setValues(const std::vector<T>& aValue)
{
   myValues = aValue;
}

template <typename T>
void DtMultiConfigVariable<T>::addValue(T aValue)
{
   myValues.push_back(aValue);
}

template <typename T>
void DtMultiConfigVariable<T>::removeValue(T aValue)
{
   typename std::vector<T>::iterator iter = myValues.begin();
   for (;iter != myValues.end(); ++iter)
   {
      if(*iter == aValue)
      {
         myValues.erase(iter);
         return;
      }
   }
}

template <typename T>
void DtMultiConfigVariable<T>::clearValues()
{
   myValues.clear();
}

template <typename T>
void DtMultiConfigVariable<T>::setName( const DtString& name )
{
   myName = name;
}

template <typename T>
void DtMultiConfigVariable<T>::setShortcut( const DtString& aShortcut )
{
   myShortcut = aShortcut;
}

