/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 * @(#)root/roofitcore:$Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// RooMultiCatIter iterators over all state permutations of a list of categories.
// It serves as the state iterator for a RooSuperCategory or a RooMultiCategory.
// Since this iterator only constructs state labels and does not change the value
// of its input categories, it is not required that its inputs are LValues.  
// For cases where all inputs are LValues (such as for RooSuperCategory) the
// values of the input can be changes by assigning the super category the
// string label generated by this iterator
// END_HTML
//

#include "RooFit.h"

#include "RooAbsCategoryLValue.h"
#include "RooAbsCategoryLValue.h"
#include "RooMultiCatIter.h"

using namespace std;

ClassImp(RooMultiCatIter)
;



//_____________________________________________________________________________
RooMultiCatIter::RooMultiCatIter(const RooArgSet& catList, const char* rangeName) : _catList("catList") 
{
  // Construct iterator over all permutations of states of categories in catList.
  // If rangeName is not null, iteration is restricted to states that are selected
  // in the given range name

  if (rangeName) {
    _rangeName = rangeName ;
  }
  initialize(catList) ;
}



//_____________________________________________________________________________
RooMultiCatIter::RooMultiCatIter(const RooMultiCatIter& other) : TIterator(other), _catList("catList")
{
  // Copy constructor

  initialize(other._catList) ;
}



//_____________________________________________________________________________
void RooMultiCatIter::initialize(const RooArgSet& catList) 
{
  // Build iterator array for given catList

  // Copy RooCategory list into internal argset
  TIterator* catIter = catList.createIterator() ;
  TObject* obj ;
  while ((obj = catIter->Next())) {
    _catList.add((RooAbsArg&)*obj) ;
  }
  delete catIter ;
  
  // Allocate storage for component iterators
  _nIter = catList.getSize() ;
  _iterList   = new pTIterator[_nIter] ;
  _catPtrList = new pRooCategory[_nIter] ;
  _curTypeList = new RooCatType[_nIter] ;

  // Construct component iterators
  _curIter = 0 ;
  _curItem = 0 ;
  TIterator* cIter = _catList.createIterator() ;
  RooAbsCategoryLValue* cat ;
  while((cat=(RooAbsCategoryLValue*)cIter->Next())) {
    _catPtrList[_curIter] = cat ;
    _iterList[_curIter] = cat->typeIterator() ;
    _iterList[_curIter]->Next() ;
//     _curTypeList[_curIter] = *first ;
//     _curTypeList[_curIter].SetName(first->GetName()) ;
//     cout << "init: _curTypeList[" << _curIter << "] set to " << first->GetName() << endl ;
//     _iterList[_curIter]->Reset() ;    
    _curIter++ ;
  }
  delete cIter ;

  Reset() ;
}



//_____________________________________________________________________________
RooMultiCatIter::~RooMultiCatIter() 
{
  // Destructor

  for (_curIter=0 ; _curIter<_nIter ; _curIter++) {
    delete _iterList[_curIter] ;
  }
  delete[] _iterList ;
  delete[] _catPtrList ;
  delete[] _curTypeList ;
}



//_____________________________________________________________________________
const TCollection* RooMultiCatIter::GetCollection() const 
{
  // Dummy implementation, always returns zero

  //return &_catList.getCollection() ;
  return 0 ;
}



//_____________________________________________________________________________
TObjString* RooMultiCatIter::compositeLabel() 
{
  // Construct string with composite object
  // label corresponding to the state name
  // of a RooMultiCategory or RooSuperCategory
  // constructed from this set of input categories

  TString& str = _compositeLabel.String() ;

  str = "{" ;
  Int_t i ;
  for (i=0 ; i<_nIter ; i++) {
    if (i>0) str.Append(";") ;
    str.Append(_curTypeList[i].GetName()) ;
  }
  str.Append("}") ;

  return &_compositeLabel ;
}



//_____________________________________________________________________________
TObject* RooMultiCatIter::Next() 
{
  // Iterator increment operator

  // Check for end
  if (_curIter==_nIter) {
    _curItem = 0;
    return 0 ;
  }

  RooCatType* next = (RooCatType*) _iterList[_curIter]->Next() ;
  if (next) { 

    // Increment current iterator
    _curTypeList[_curIter] = *next ;
    _curTypeList[_curIter].SetName(next->GetName()) ;
    
    // If higher order increment was successful, reset master iterator
    if (_curIter>0) _curIter=0 ;

    _curItem = compositeLabel() ;
    return _curItem ;    
  } else {

    // Reset current iterator
    _iterList[_curIter]->Reset() ;
    next = (RooCatType*) _iterList[_curIter]->Next() ;
    if (next) {
      _curTypeList[_curIter] = *next ; 
      _curTypeList[_curIter].SetName(next->GetName()) ;
    }
    //if (next) _catPtrList[_curIter]->setIndex(next->getVal()) ;

    // Increment next iterator 
    _curIter++ ;
    _curItem = Next() ;
    return _curItem ;
  }
}



//_____________________________________________________________________________
void RooMultiCatIter::Reset() 
{
  // Rewind master iterator

  for (_curIter=0 ; _curIter<_nIter ; _curIter++) {
    TIterator* cIter = _iterList[_curIter] ;
    cIter->Reset() ;
    RooCatType* first = (RooCatType*) cIter->Next() ;
    if (first) {
      if (_curIter==0) cIter->Reset() ;
      _curTypeList[_curIter] = *first ;
      _curTypeList[_curIter].SetName(first->GetName()) ;
    }
  }
  _curIter=0 ;
}


//_____________________________________________________________________________
TObject *RooMultiCatIter::operator*() const
{
  // Return current item (dummy)
  return _curItem ;
}


//_____________________________________________________________________________
bool RooMultiCatIter::operator!=(const TIterator &aIter) const
{
  // Comparison operator to other iterator
  // Returns true if both iterator iterate over the
  // same set of input categories and are not at the
  // same sequential position

   if ((aIter.IsA() == RooMultiCatIter::Class())) {
      const RooMultiCatIter &iter(dynamic_cast<const RooMultiCatIter &>(aIter));
      return (_curItem != iter._curItem);
   }
   
   return false;
}

 RooMultiCatIter.cxx:1
 RooMultiCatIter.cxx:2
 RooMultiCatIter.cxx:3
 RooMultiCatIter.cxx:4
 RooMultiCatIter.cxx:5
 RooMultiCatIter.cxx:6
 RooMultiCatIter.cxx:7
 RooMultiCatIter.cxx:8
 RooMultiCatIter.cxx:9
 RooMultiCatIter.cxx:10
 RooMultiCatIter.cxx:11
 RooMultiCatIter.cxx:12
 RooMultiCatIter.cxx:13
 RooMultiCatIter.cxx:14
 RooMultiCatIter.cxx:15
 RooMultiCatIter.cxx:16
 RooMultiCatIter.cxx:17
 RooMultiCatIter.cxx:18
 RooMultiCatIter.cxx:19
 RooMultiCatIter.cxx:20
 RooMultiCatIter.cxx:21
 RooMultiCatIter.cxx:22
 RooMultiCatIter.cxx:23
 RooMultiCatIter.cxx:24
 RooMultiCatIter.cxx:25
 RooMultiCatIter.cxx:26
 RooMultiCatIter.cxx:27
 RooMultiCatIter.cxx:28
 RooMultiCatIter.cxx:29
 RooMultiCatIter.cxx:30
 RooMultiCatIter.cxx:31
 RooMultiCatIter.cxx:32
 RooMultiCatIter.cxx:33
 RooMultiCatIter.cxx:34
 RooMultiCatIter.cxx:35
 RooMultiCatIter.cxx:36
 RooMultiCatIter.cxx:37
 RooMultiCatIter.cxx:38
 RooMultiCatIter.cxx:39
 RooMultiCatIter.cxx:40
 RooMultiCatIter.cxx:41
 RooMultiCatIter.cxx:42
 RooMultiCatIter.cxx:43
 RooMultiCatIter.cxx:44
 RooMultiCatIter.cxx:45
 RooMultiCatIter.cxx:46
 RooMultiCatIter.cxx:47
 RooMultiCatIter.cxx:48
 RooMultiCatIter.cxx:49
 RooMultiCatIter.cxx:50
 RooMultiCatIter.cxx:51
 RooMultiCatIter.cxx:52
 RooMultiCatIter.cxx:53
 RooMultiCatIter.cxx:54
 RooMultiCatIter.cxx:55
 RooMultiCatIter.cxx:56
 RooMultiCatIter.cxx:57
 RooMultiCatIter.cxx:58
 RooMultiCatIter.cxx:59
 RooMultiCatIter.cxx:60
 RooMultiCatIter.cxx:61
 RooMultiCatIter.cxx:62
 RooMultiCatIter.cxx:63
 RooMultiCatIter.cxx:64
 RooMultiCatIter.cxx:65
 RooMultiCatIter.cxx:66
 RooMultiCatIter.cxx:67
 RooMultiCatIter.cxx:68
 RooMultiCatIter.cxx:69
 RooMultiCatIter.cxx:70
 RooMultiCatIter.cxx:71
 RooMultiCatIter.cxx:72
 RooMultiCatIter.cxx:73
 RooMultiCatIter.cxx:74
 RooMultiCatIter.cxx:75
 RooMultiCatIter.cxx:76
 RooMultiCatIter.cxx:77
 RooMultiCatIter.cxx:78
 RooMultiCatIter.cxx:79
 RooMultiCatIter.cxx:80
 RooMultiCatIter.cxx:81
 RooMultiCatIter.cxx:82
 RooMultiCatIter.cxx:83
 RooMultiCatIter.cxx:84
 RooMultiCatIter.cxx:85
 RooMultiCatIter.cxx:86
 RooMultiCatIter.cxx:87
 RooMultiCatIter.cxx:88
 RooMultiCatIter.cxx:89
 RooMultiCatIter.cxx:90
 RooMultiCatIter.cxx:91
 RooMultiCatIter.cxx:92
 RooMultiCatIter.cxx:93
 RooMultiCatIter.cxx:94
 RooMultiCatIter.cxx:95
 RooMultiCatIter.cxx:96
 RooMultiCatIter.cxx:97
 RooMultiCatIter.cxx:98
 RooMultiCatIter.cxx:99
 RooMultiCatIter.cxx:100
 RooMultiCatIter.cxx:101
 RooMultiCatIter.cxx:102
 RooMultiCatIter.cxx:103
 RooMultiCatIter.cxx:104
 RooMultiCatIter.cxx:105
 RooMultiCatIter.cxx:106
 RooMultiCatIter.cxx:107
 RooMultiCatIter.cxx:108
 RooMultiCatIter.cxx:109
 RooMultiCatIter.cxx:110
 RooMultiCatIter.cxx:111
 RooMultiCatIter.cxx:112
 RooMultiCatIter.cxx:113
 RooMultiCatIter.cxx:114
 RooMultiCatIter.cxx:115
 RooMultiCatIter.cxx:116
 RooMultiCatIter.cxx:117
 RooMultiCatIter.cxx:118
 RooMultiCatIter.cxx:119
 RooMultiCatIter.cxx:120
 RooMultiCatIter.cxx:121
 RooMultiCatIter.cxx:122
 RooMultiCatIter.cxx:123
 RooMultiCatIter.cxx:124
 RooMultiCatIter.cxx:125
 RooMultiCatIter.cxx:126
 RooMultiCatIter.cxx:127
 RooMultiCatIter.cxx:128
 RooMultiCatIter.cxx:129
 RooMultiCatIter.cxx:130
 RooMultiCatIter.cxx:131
 RooMultiCatIter.cxx:132
 RooMultiCatIter.cxx:133
 RooMultiCatIter.cxx:134
 RooMultiCatIter.cxx:135
 RooMultiCatIter.cxx:136
 RooMultiCatIter.cxx:137
 RooMultiCatIter.cxx:138
 RooMultiCatIter.cxx:139
 RooMultiCatIter.cxx:140
 RooMultiCatIter.cxx:141
 RooMultiCatIter.cxx:142
 RooMultiCatIter.cxx:143
 RooMultiCatIter.cxx:144
 RooMultiCatIter.cxx:145
 RooMultiCatIter.cxx:146
 RooMultiCatIter.cxx:147
 RooMultiCatIter.cxx:148
 RooMultiCatIter.cxx:149
 RooMultiCatIter.cxx:150
 RooMultiCatIter.cxx:151
 RooMultiCatIter.cxx:152
 RooMultiCatIter.cxx:153
 RooMultiCatIter.cxx:154
 RooMultiCatIter.cxx:155
 RooMultiCatIter.cxx:156
 RooMultiCatIter.cxx:157
 RooMultiCatIter.cxx:158
 RooMultiCatIter.cxx:159
 RooMultiCatIter.cxx:160
 RooMultiCatIter.cxx:161
 RooMultiCatIter.cxx:162
 RooMultiCatIter.cxx:163
 RooMultiCatIter.cxx:164
 RooMultiCatIter.cxx:165
 RooMultiCatIter.cxx:166
 RooMultiCatIter.cxx:167
 RooMultiCatIter.cxx:168
 RooMultiCatIter.cxx:169
 RooMultiCatIter.cxx:170
 RooMultiCatIter.cxx:171
 RooMultiCatIter.cxx:172
 RooMultiCatIter.cxx:173
 RooMultiCatIter.cxx:174
 RooMultiCatIter.cxx:175
 RooMultiCatIter.cxx:176
 RooMultiCatIter.cxx:177
 RooMultiCatIter.cxx:178
 RooMultiCatIter.cxx:179
 RooMultiCatIter.cxx:180
 RooMultiCatIter.cxx:181
 RooMultiCatIter.cxx:182
 RooMultiCatIter.cxx:183
 RooMultiCatIter.cxx:184
 RooMultiCatIter.cxx:185
 RooMultiCatIter.cxx:186
 RooMultiCatIter.cxx:187
 RooMultiCatIter.cxx:188
 RooMultiCatIter.cxx:189
 RooMultiCatIter.cxx:190
 RooMultiCatIter.cxx:191
 RooMultiCatIter.cxx:192
 RooMultiCatIter.cxx:193
 RooMultiCatIter.cxx:194
 RooMultiCatIter.cxx:195
 RooMultiCatIter.cxx:196
 RooMultiCatIter.cxx:197
 RooMultiCatIter.cxx:198
 RooMultiCatIter.cxx:199
 RooMultiCatIter.cxx:200
 RooMultiCatIter.cxx:201
 RooMultiCatIter.cxx:202
 RooMultiCatIter.cxx:203
 RooMultiCatIter.cxx:204
 RooMultiCatIter.cxx:205
 RooMultiCatIter.cxx:206
 RooMultiCatIter.cxx:207
 RooMultiCatIter.cxx:208
 RooMultiCatIter.cxx:209
 RooMultiCatIter.cxx:210
 RooMultiCatIter.cxx:211
 RooMultiCatIter.cxx:212
 RooMultiCatIter.cxx:213
 RooMultiCatIter.cxx:214
 RooMultiCatIter.cxx:215
 RooMultiCatIter.cxx:216
 RooMultiCatIter.cxx:217
 RooMultiCatIter.cxx:218
 RooMultiCatIter.cxx:219
 RooMultiCatIter.cxx:220
 RooMultiCatIter.cxx:221
 RooMultiCatIter.cxx:222
 RooMultiCatIter.cxx:223
 RooMultiCatIter.cxx:224
 RooMultiCatIter.cxx:225
 RooMultiCatIter.cxx:226
 RooMultiCatIter.cxx:227
 RooMultiCatIter.cxx:228
 RooMultiCatIter.cxx:229
 RooMultiCatIter.cxx:230
 RooMultiCatIter.cxx:231
 RooMultiCatIter.cxx:232
 RooMultiCatIter.cxx:233
 RooMultiCatIter.cxx:234
 RooMultiCatIter.cxx:235
 RooMultiCatIter.cxx:236
 RooMultiCatIter.cxx:237
 RooMultiCatIter.cxx:238
 RooMultiCatIter.cxx:239
 RooMultiCatIter.cxx:240
 RooMultiCatIter.cxx:241
 RooMultiCatIter.cxx:242
 RooMultiCatIter.cxx:243