// -*- mode: c++ -*- 
/* 

    GIFT, a flexible content based image retrieval system.
    Copyright (C) 1998, 1999, 2000 CUI, University of Geneva

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/
#include "mrml_const.h" // for parsing
#include "CQHierarchy.h"
#include "CAcHierarchy.h"
/** 

    There is no special initialisation to do,
    so this function is empty

 */

void CQHierarchy::init(){
  mCurrentPath.clear();
};

/**
 *
 * default constructor SHOULD NOT BE CALLED
 * 
 */
CQHierarchy::CQHierarchy(){
  assert(0);
};
/**
 * constructor
 * see CQuery
 */
CQHierarchy::CQHierarchy(CAccessorCollection& inAccessorCollection,
			 CAlgorithm&          inAlgorithm):
  CQuery(inAccessorCollection,
	 inAlgorithm){
  {

    // mproxy has been filled in a reasonable way 
    // by CQuery::CQuery
    mAccessor=mProxy->openAccessor("hierarchy");

    init();

    assert(mAccessor);
  }
};
    
/**
 *
 * destructor: at present empty
 * 
 */
CQHierarchy::~CQHierarchy(){

  cout << "destroying this "
       << __FILE__
       << __LINE__
       << flush
       << endl;

  //i thought i will need this, but at present I do not have this impression
  //it does not hurt, so we leave it in
};

/** everything happening in the children */
bool CQHierarchy::setAlgorithm(CAlgorithm & inAlgorithm){
  if(mAlgorithm && mAlgorithm->getCollectionID()==inAlgorithm.getCollectionID()){
    
    return true;
    
  }else{
    //close the old collection, if exsisting
    if(mProxy)
      mProxy->closeAccessor("hierarchy");
    //
    mProxy=&mAccessorCollection->getProxy(inAlgorithm.getCollectionID());
    mAccessor=mProxy->openAccessor("hierarchy");
    
    assert(mAccessor);
    //
    return (CQuery::setAlgorithm(inAlgorithm) && mAccessor);
  }
};
/**
 *
 * calls fastQuery for every child, merges the results
 * and translates them back into URLs
 *
 */
CIDRelevanceLevelPairList* CQHierarchy::fastQuery(const CXMLElement& inQuery,
						 int inNumberOfInterestingImages,
						 double inDifferenceToBest){

  CIDRelevanceLevelPairList* lReturnValue(0);

  for(list<CXMLElement*>::const_iterator i=inQuery.child_list_begin();
      i!=inQuery.child_list_end();
      i++){

     cout << "I:The name of this tree element: "
 	 << endl
 	 << (*i)->getName()
 	 << endl;
     if((*i)->getName()==mrml_const::cui_hierarchy_up){
       if(mCurrentPath.size()){
	 cout << "MOVING UP ";
	 copy(mCurrentPath.begin(),
	      mCurrentPath.end(),
	      ostream_iterator<TID>(cout,","));
	 cout << endl;       
	 mCurrentPath.pop_back();
	 copy(mCurrentPath.begin(),
	      mCurrentPath.end(),
	      ostream_iterator<TID>(cout,","));
	 return ((CAcHierarchy*)mAccessor)->getChildren(mCurrentPath);
       }
       return new CIDRelevanceLevelPairList();
     }
     if((*i)->getName()==mrml_const::user_relevance_element_list){
       for(list<CXMLElement*>::const_iterator j=(*i)->child_list_begin();
	   j!=(*i)->child_list_end();
	   j++){
	 cout << "J:The name of this tree element: "
	      << endl
	      << (*j)->getName()
	      << endl;
	 if((*j)->getName()==mrml_const::user_relevance_element){
	   if(((*j)->stringReadAttribute(mrml_const::image_location).first)
	      &&
	      ((*j)->stringReadAttribute(mrml_const::user_relevance).first)){
	     
	     if((*j)->doubleReadAttribute(mrml_const::user_relevance).second){
	       if(!lReturnValue){
		 list<TID> lOldCurrentPath=mCurrentPath;
		 mCurrentPath.push_back(mAccessor->URLToID((*j)->stringReadAttribute(mrml_const::image_location).second).second);
		 
		 cout << "The new mCurrentPath: ";
		 copy(mCurrentPath.begin(),
		      mCurrentPath.end(),
		      ostream_iterator<TID>(cout,","));
		 cout << endl;
		 
		 lReturnValue=((CAcHierarchy*)mAccessor)->getChildren(mCurrentPath);
		 if(lReturnValue){
		   return lReturnValue;
		 }else{
		   mCurrentPath=lOldCurrentPath;
		   lReturnValue=((CAcHierarchy*)mAccessor)->getChildren(mCurrentPath);
		   return lReturnValue;
		 }
	       }
	     }
	   }
	 }
       }
     }
  }

  mCurrentPath.clear();
  return ((CAcHierarchy*)mAccessor)->getChildren(mCurrentPath);
};

