// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1996
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        tifs.h
// 
// Purpose:     
// 
// Created:     26 Jan 1997   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// $Id: tifs.C,v 1.3 1997/02/19 16:34:23 jfasch Exp $
// 
// $Log: tifs.C,v $
// Revision 1.3  1997/02/19 16:34:23  jfasch
// instance() creates TIOINETFactoryDirect as default. no need to set it
// explicitly anymore.
//
// Revision 1.2  1997/02/12 23:13:11  jfasch
// moved from HgDcCommon
//
// Revision 1.1  1997/02/04 13:48:16  jfasch
// Initial revision
//
// 
// </file> 
#include "tifs.h"

#include "tifdirect.h"

#include <hyperg/utils/assert.h>
#include <hyperg/utils/new.h>

// --------------------------------------------------------------------
Dequeimplement (TIOINETFactoriesBase, TIOINETFactoryPtr) ;

// --------------------------------------------------------------------
TIOINETFactories* TIOINETFactories :: instance_ = nil ;
Verbose TIOINETFactories :: verbose ;
const char* TIOINETFactories :: version1 = "TIOINETFactories: $Id: tifs.C,v 1.3 1997/02/19 16:34:23 jfasch Exp $" ;

TIOINETFactories :: ~TIOINETFactories() {
   hgassert (!running_, "TIOINETFactories::~TIOINETFactories(): still active") ;
}

void TIOINETFactories :: start() {
   hgassert (!running_, "TIOINETFactories::start(): already running") ;
   for (int i=0 ; i<TIOINETFactoriesBase::count() ; i++) {
      hgassert (operator[](i), "TIOINETFactories::start(): element "<<i<<" is nil") ;
      operator[](i).ptr()->start() ;
   }
   running_ = true ;
}

void TIOINETFactories :: stop() {
   hgassert (running_, "TIOINETFactories::stop(): not yet running") ;
   for (int i=0 ; i<TIOINETFactoriesBase::count() ; i++) {
      hgassert (operator[](i), "TIOINETFactories::stop(): element "<<i<<" is nil") ;
      operator[](i).ptr()->stop() ;
   }
   running_ = false ;
}

TIOINETResponsePtr TIOINETFactories :: connect (const TIOINETRequestPtr& r) {
   hgassert (running_, "TIOINETFactories::connect(): not yet running") ;
   hgassert (r, "TIOINETFactories::connect(): nil request") ;
   // I need not do this. I dont handle any requests by myself, I just
   // forward them to my slaves. this is just to make sure every slave
   // behaves correctly and overrides me as the worker. if not, the
   // issuer will hit me on cancel, and I will hit an
   // assertion. boom. (its the only way to detect misbehavior).
   set_worker_(r) ;

   // iterate through my slaves. a nil response or an error response
   // other than the explicit TIFNEXT error indicate an immediate
   // error.
   TIOINETResponsePtr res ;
   for (int i=0 ; i<TIOINETFactoriesBase::count() ; i++) {
      hgassert (operator[](i), "TIOINETFactories::connect(): element "<<i<<" is nil") ;
      res = operator[](i).ptr()->connect (r) ;
      if (!res || res.ptr()->error()!=TIOINETFactory::TIFNEXT)
         return res ;
   }
   DEBUGNL ("TIOINETFactories::connect(): at the end of my list") ;
   return TIOINETResponsePtr (HGNEW (TIOINETResponse (r.ptr(), TIOINETFactory::TIFNOCONN))) ;
}

TIOINETFactories& TIOINETFactories :: instance() {
   if (! instance_) {
      DEBUGNL ("TIOINETFactories::instance(): not yet initialized, creating default") ;
      instance_ = HGNEW (TIOINETFactories) ;
      instance_->push (TIOINETFactoryPtr (HGNEW (TIOINETFactoryDirect))) ;
      instance_->start() ;
   }
   return *instance_ ;
}

void TIOINETFactories :: instance (TIOINETFactories* f) {
   if (instance_) {
      instance_->stop() ;
      HGDELETE (instance_) ;
   }
   instance_ = f ;
}

void TIOINETFactories :: do_cancel_(const TIOINETRequest* r) {
   hgassert (false, "TIOINETFactories::do_cancel_("<<r<<"): "
             "I do not work any requests myself") ;
}
