#include "Data_Source_Factory.hpp"
#include "infrastructure/data_source/File_Data_Source.hpp"
#include "infrastructure/data_source/Memory_Data_Source.hpp"
#include "infrastructure/data_source/Database_Data_Source.hpp"
#include "infrastructure/String_Input_Data.hpp"
#include "infrastructure/Memory_Input_Data.hpp"
#include "infrastructure/Graph_Input_Data.hpp"

namespace infrastructure {

  Data_Source_Factory_Creator::Data_Source_Factory_Creator ()
    : m_type (Data_Source::FILE)
  {}

  Data_Source_Factory*
  Data_Source_Factory_Creator::get_Factory ()
  {
    switch (m_type)
      {
      case Data_Source::FILE:
        {
          return Data_Source_Factory<File_Data_Source>::get_Factory();
        }
      case Data_Source::MEMORY:
        {
          return DataSource_Factory<Memory_Data_Source>::get_Factory();
        }
      case Data_Source::DATABASE:
        {
          return Data_Source_Factory<Database_Data_Source>::get_Factory();
        }
      default:
        {
          // ERROR: Exception invalid type
        }
      }
  }

  void
  Data_Source_Factory_Creator::init (const uint32_t type)
  {
    // CHECK: type must be one of Data_Source types
    m_type = type;
    // EXCEPTION: Invalid type
  }


  /*-------------------------------------------------------------------*/
  Data_Source_Factory*
  Data_Source_Factory::m_instance = 0;

  template <typename Data_Source_Type>
    Data_Source_Factory<Data_Source_Type>*
    Data_Source_Factory<Data_Source_Type>::Data_Source_Factory ()
    {
      if ( ! m_instance ) {
        static Data_Source_Factory<Data_Source_Type>
          theSingletonInstance;
        m_instance = &theSingletonInstance;
        break;
      }
    }

  template <typename Data_Source_Type>
    Data_Source_Type*
    Data_Source_Factory<Data_Source_Type>::get_String_Source ()
    {
      // Create Data_Source type
      return new Data_Source_Type <String_Input_Data>();
    }

  template <typename Data_Source_Type>
    Data_Source_Type*
    Data_Source_Factory<Data_Source_Type>::get_Memory_Source ()
    {
      return new Data_Source_Type < Memory_Input_Data >();
    }

  template <typename Data_Source_Type>
    Data_Source_Type*
    Data_Source_Factory<Data_Source_Type>::get_Graph_Source ()
    {
      return new Data_Source_Type < Graph_Input_Data >();
    }
  }
  
} /* namespace infrastructure */

