/*************************************************
* Engine Source File                             *
* (C) 1999-2004 The Botan Project                *
*************************************************/

#include <botan/engine.h>
#include <botan/eng_def.h>
#include <botan/init.h>

namespace Botan {

namespace {

std::vector<Engine*> engines;

}

namespace Init {

/*************************************************
* Initialize the list of Engines                 *
*************************************************/
void startup_engines()
   {
   engines.push_back(new Default_Engine);
   }

/*************************************************
* Delete the list of Engines                     *
*************************************************/
void shutdown_engines()
   {
   for(u32bit j = 0; j != engines.size(); j++)
      delete engines[j];
   engines.clear();
   }

}

namespace Engine_Core {

/*************************************************
* Add an Engine to the list                      *
*************************************************/
void add_engine(Engine* engine)
   {
   engines.insert(engines.end() - 1, engine);
   }

/*************************************************
* Acquire an IF op                               *
*************************************************/
IF_Operation* if_op(const BigInt& e, const BigInt& n, const BigInt& d,
                    const BigInt& p, const BigInt& q, const BigInt& d1,
                    const BigInt& d2, const BigInt& c)
   {
   for(u32bit j = 0; j != engines.size(); j++)
      {
      IF_Operation* op = engines[j]->if_op(e, n, d, p, q, d1, d2, c);
      if(op) return op;
      }
   throw Lookup_Error("Engine_Core::if_op: Unable to find a working engine");
   }

/*************************************************
* Acquire a DSA op                               *
*************************************************/
DSA_Operation* dsa_op(const DL_Group& group, const BigInt& y, const BigInt& x)
   {
   for(u32bit j = 0; j != engines.size(); j++)
      {
      DSA_Operation* op = engines[j]->dsa_op(group, y, x);
      if(op) return op;
      }
   throw Lookup_Error("Engine_Core::dsa_op: Unable to find a working engine");
   }

/*************************************************
* Acquire a NR op                                *
*************************************************/
NR_Operation* nr_op(const DL_Group& group, const BigInt& y, const BigInt& x)
   {
   for(u32bit j = 0; j != engines.size(); j++)
      {
      NR_Operation* op = engines[j]->nr_op(group, y, x);
      if(op) return op;
      }
   throw Lookup_Error("Engine_Core::nr_op: Unable to find a working engine");
   }

/*************************************************
* Acquire an ElGamal op                          *
*************************************************/
ELG_Operation* elg_op(const DL_Group& group, const BigInt& y, const BigInt& x)
   {
   for(u32bit j = 0; j != engines.size(); j++)
      {
      ELG_Operation* op = engines[j]->elg_op(group, y, x);
      if(op) return op;
      }
   throw Lookup_Error("Engine_Core::elg_op: Unable to find a working engine");
   }

/*************************************************
* Acquire a DH op                                *
*************************************************/
DH_Operation* dh_op(const DL_Group& group, const BigInt& x)
   {
   for(u32bit j = 0; j != engines.size(); j++)
      {
      DH_Operation* op = engines[j]->dh_op(group, x);
      if(op) return op;
      }
   throw Lookup_Error("Engine_Core::dh_op: Unable to find a working engine");
   }

}

/*************************************************
* Acquire a modular reducer                      *
*************************************************/
ModularReducer* get_reducer(const BigInt& n, bool convert_ok)
   {
   for(u32bit j = 0; j != engines.size(); j++)
      {
      ModularReducer* op = engines[j]->reducer(n, convert_ok);
      if(op) return op;
      }
   throw Lookup_Error("get_reducer: Unable to find a working engine");
   }

/*************************************************
* Basic No-Op Engine Implementation              *
*************************************************/
IF_Operation* Engine::if_op(const BigInt&, const BigInt&, const BigInt&,
                            const BigInt&, const BigInt&, const BigInt&,
                            const BigInt&, const BigInt&) const
   {
   return 0;
   }

/*************************************************
* Basic No-Op Engine Implementation              *
*************************************************/
DSA_Operation* Engine::dsa_op(const DL_Group&, const BigInt&,
                              const BigInt&) const
   {
   return 0;
   }

/*************************************************
* Basic No-Op Engine Implementation              *
*************************************************/
NR_Operation* Engine::nr_op(const DL_Group&, const BigInt&,
                            const BigInt&) const
   {
   return 0;
   }

/*************************************************
* Basic No-Op Engine Implementation              *
*************************************************/
ELG_Operation* Engine::elg_op(const DL_Group&, const BigInt&,
                              const BigInt&) const
   {
   return 0;
   }

/*************************************************
* Basic No-Op Engine Implementation              *
*************************************************/
DH_Operation* Engine::dh_op(const DL_Group&, const BigInt&) const
   {
   return 0;
   }

/*************************************************
* Basic No-Op Engine Implementation              *
*************************************************/
ModularReducer* Engine::reducer(const BigInt&, bool) const
   {
   return 0;
   }

}
