/*****************************************************************************
 * 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
// RooSuperCategory consolidates several RooAbsCategoryLValue objects into
// a single category. The states of the super category consist of all the permutations
// of the input categories. The super category is an lvalue and requires that
// all input categories are lvalues as well as modification
// of its state will back propagate into a modification of its input categories.
// To define a consolidated category of multiple non-lvalye categories
// use class RooMultiCategory
// <p>
// RooSuperCategory state are automatically defined and updated whenever an input
// category modifies its list of states
// END_HTML
//

#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include <stdlib.h>
#include <stdio.h>
#include "TString.h"
#include "TClass.h"
#include "RooSuperCategory.h"
#include "RooStreamParser.h"
#include "RooArgSet.h"
#include "RooMultiCatIter.h"
#include "RooAbsCategoryLValue.h"
#include "RooMsgService.h"

using namespace std;

ClassImp(RooSuperCategory)
;


//_____________________________________________________________________________
RooSuperCategory::RooSuperCategory(const char *name, const char *title, const RooArgSet& inInputCatList) :
  RooAbsCategoryLValue(name, title), _catSet("input","Input category set",this,kTRUE,kTRUE)
{  
  // Construct a lvalue product of the given set of input RooAbsCategoryLValues in 'inInputCatList'
  // The state names of this product category are {S1;S2,S3,...Sn} where Si are the state names
  // of the input categories. A RooSuperCategory is an lvalue.

  // Copy category list
  TIterator* iter = inInputCatList.createIterator() ;
  RooAbsArg* arg ;
  while ((arg=(RooAbsArg*)iter->Next())) {
    if (!arg->IsA()->InheritsFrom(RooAbsCategoryLValue::Class())) {
      coutE(InputArguments) << "RooSuperCategory::RooSuperCategory(" << GetName() << "): input category " << arg->GetName() 
			    << " is not an lvalue" << endl ;
    }
    _catSet.add(*arg) ;
  }
  delete iter ;
  _catIter = _catSet.createIterator() ;
  
  updateIndexList() ;
}



//_____________________________________________________________________________
RooSuperCategory::RooSuperCategory(const RooSuperCategory& other, const char *name) :
  RooAbsCategoryLValue(other,name), _catSet("input",this,other._catSet)
{
  // Copy constructor

  _catIter = _catSet.createIterator() ;
  updateIndexList() ;
  setIndex(other.getIndex()) ;
}



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

  delete _catIter ;
}



//_____________________________________________________________________________
TIterator* RooSuperCategory::MakeIterator() const 
{
  // Make an iterator over all state permutations of 
  // the input categories of this supercategory

  return new RooMultiCatIter(_catSet) ;
}



//_____________________________________________________________________________
void RooSuperCategory::updateIndexList()
{
  // Update the list of possible states of this super category
  
  clearTypes() ;

  RooMultiCatIter mcIter(_catSet) ;
  TObjString* obj ;
  Int_t i(0) ;
  while((obj = (TObjString*) mcIter.Next())) {
    // Register composite label
    defineTypeUnchecked(obj->String(),i++) ;
  }

  // Renumbering will invalidate cache
  setValueDirty() ;
}



//_____________________________________________________________________________
TString RooSuperCategory::currentLabel() const
{
  // Return the name of the current state, 
  // constructed from the state names of the input categories

  _catIter->Reset() ;

  // Construct composite label name
  TString label ;
  RooAbsCategory* cat ;
  Bool_t first(kTRUE) ;
  while((cat=(RooAbsCategory*) _catIter->Next())) {
    label.Append(first?"{":";") ;
    label.Append(cat->getLabel()) ;      
    first=kFALSE ;
  }
  label.Append("}") ;  

  return label ;
}



//_____________________________________________________________________________
RooCatType RooSuperCategory::evaluate() const
{
  // Calculate and return the current value 

  if (isShapeDirty()) {
    const_cast<RooSuperCategory*>(this)->updateIndexList() ;
  }
  const RooCatType* ret = lookupType(currentLabel(),kTRUE) ;
  if (!ret) {
    coutE(Eval) << "RooSuperCat::evaluate(" << this << ") error: current state not defined: '" << currentLabel() << "'" << endl ;
    printStream(ccoutE(Eval),0,kVerbose) ;
    return RooCatType() ;
  }
  return *ret ;
}



//_____________________________________________________________________________
Bool_t RooSuperCategory::setIndex(Int_t index, Bool_t /*printError*/) 
{
  // Set the value of the super category by specifying the state index code
  // by setting the states of the corresponding input category lvalues

  const RooCatType* type = lookupType(index,kTRUE) ;
  if (!type) return kTRUE ;
  return setType(type) ;
}



//_____________________________________________________________________________
Bool_t RooSuperCategory::setLabel(const char* label, Bool_t /*printError*/) 
{
  // Set the value of the super category by specifying the state name
  // by setting the state names of the corresponding input category lvalues

  const RooCatType* type = lookupType(label,kTRUE) ;
  if (!type) return kTRUE ;
  return setType(type) ;
}



//_____________________________________________________________________________
Bool_t RooSuperCategory::setType(const RooCatType* type, Bool_t /*printError*/)
{
  // Set the value of the super category by specifying the state object
  // by setting the state names of the corresponding input category lvalues

  char buf[1024] ;
  strlcpy(buf,type->GetName(),1024) ;

  RooAbsCategoryLValue* arg ;
  Bool_t error(kFALSE) ;

  // Parse composite label and set label of components to their values  
  char* ptr=buf+1 ;
  char* token = ptr ;
  _catIter->Reset() ;
  while ((arg=(RooAbsCategoryLValue*)_catIter->Next())) {

    // Delimit name token for this category
    if (*ptr=='{') {
      // Token is composite itself, terminate at matching '}'
      Int_t nBrak(1) ;
      while(*(++ptr)) {
	if (nBrak==0) {
	  *ptr = 0 ;
	  break ;
	}
	if (*ptr=='{') {
	  nBrak++ ;
	} else if (*ptr=='}') {
	  nBrak-- ;
	}
      }	
    } else {
      // Simple token, terminate at next semi-colon
      ptr = strtok(ptr,";}") ;
      ptr += strlen(ptr) ;
    }

    error |= arg->setLabel(token) ;
    token = ++ptr ;
  }
  
  return error ;
}



//_____________________________________________________________________________
void RooSuperCategory::printMultiline(ostream& os, Int_t content, Bool_t verbose, TString indent) const
{
  // Print the state of this object to the specified output stream.

  RooAbsCategory::printMultiline(os,content,verbose,indent) ;
  
  if (verbose) {     
    os << indent << "--- RooSuperCategory ---" << endl;
    os << indent << "  Input category list:" << endl ;
    TString moreIndent(indent) ;
    os << moreIndent << _catSet << endl ;
  }
}



//_____________________________________________________________________________
Bool_t RooSuperCategory::readFromStream(istream& /*is*/, Bool_t /*compact*/, Bool_t /*verbose*/) 
{
  // Read object contents from given stream

  return kTRUE ;
}



//_____________________________________________________________________________
void RooSuperCategory::writeToStream(ostream& os, Bool_t compact) const
{
  // Write object contents to given stream

  RooAbsCategory::writeToStream(os,compact) ;
}



//_____________________________________________________________________________
Bool_t RooSuperCategory::inRange(const char* rangeName) const 
{
  // Return true of all of the input category states are in the given range

  _catIter->Reset() ;
  RooAbsCategoryLValue* cat ;
  while((cat = (RooAbsCategoryLValue*)_catIter->Next())) {
    if (!cat->inRange(rangeName)) {
      return kFALSE ;
    }
  }
  return kTRUE ;
}



//_____________________________________________________________________________
Bool_t RooSuperCategory::hasRange(const char* rangeName) const 
{
  // Return true if any of the input categories has a range
  // named 'rangeName'

  _catIter->Reset() ;
  RooAbsCategoryLValue* cat ;
  while((cat = (RooAbsCategoryLValue*)_catIter->Next())) {
    if (cat->hasRange(rangeName)) return kTRUE ;
  }

  return kFALSE ;
}
 RooSuperCategory.cxx:1
 RooSuperCategory.cxx:2
 RooSuperCategory.cxx:3
 RooSuperCategory.cxx:4
 RooSuperCategory.cxx:5
 RooSuperCategory.cxx:6
 RooSuperCategory.cxx:7
 RooSuperCategory.cxx:8
 RooSuperCategory.cxx:9
 RooSuperCategory.cxx:10
 RooSuperCategory.cxx:11
 RooSuperCategory.cxx:12
 RooSuperCategory.cxx:13
 RooSuperCategory.cxx:14
 RooSuperCategory.cxx:15
 RooSuperCategory.cxx:16
 RooSuperCategory.cxx:17
 RooSuperCategory.cxx:18
 RooSuperCategory.cxx:19
 RooSuperCategory.cxx:20
 RooSuperCategory.cxx:21
 RooSuperCategory.cxx:22
 RooSuperCategory.cxx:23
 RooSuperCategory.cxx:24
 RooSuperCategory.cxx:25
 RooSuperCategory.cxx:26
 RooSuperCategory.cxx:27
 RooSuperCategory.cxx:28
 RooSuperCategory.cxx:29
 RooSuperCategory.cxx:30
 RooSuperCategory.cxx:31
 RooSuperCategory.cxx:32
 RooSuperCategory.cxx:33
 RooSuperCategory.cxx:34
 RooSuperCategory.cxx:35
 RooSuperCategory.cxx:36
 RooSuperCategory.cxx:37
 RooSuperCategory.cxx:38
 RooSuperCategory.cxx:39
 RooSuperCategory.cxx:40
 RooSuperCategory.cxx:41
 RooSuperCategory.cxx:42
 RooSuperCategory.cxx:43
 RooSuperCategory.cxx:44
 RooSuperCategory.cxx:45
 RooSuperCategory.cxx:46
 RooSuperCategory.cxx:47
 RooSuperCategory.cxx:48
 RooSuperCategory.cxx:49
 RooSuperCategory.cxx:50
 RooSuperCategory.cxx:51
 RooSuperCategory.cxx:52
 RooSuperCategory.cxx:53
 RooSuperCategory.cxx:54
 RooSuperCategory.cxx:55
 RooSuperCategory.cxx:56
 RooSuperCategory.cxx:57
 RooSuperCategory.cxx:58
 RooSuperCategory.cxx:59
 RooSuperCategory.cxx:60
 RooSuperCategory.cxx:61
 RooSuperCategory.cxx:62
 RooSuperCategory.cxx:63
 RooSuperCategory.cxx:64
 RooSuperCategory.cxx:65
 RooSuperCategory.cxx:66
 RooSuperCategory.cxx:67
 RooSuperCategory.cxx:68
 RooSuperCategory.cxx:69
 RooSuperCategory.cxx:70
 RooSuperCategory.cxx:71
 RooSuperCategory.cxx:72
 RooSuperCategory.cxx:73
 RooSuperCategory.cxx:74
 RooSuperCategory.cxx:75
 RooSuperCategory.cxx:76
 RooSuperCategory.cxx:77
 RooSuperCategory.cxx:78
 RooSuperCategory.cxx:79
 RooSuperCategory.cxx:80
 RooSuperCategory.cxx:81
 RooSuperCategory.cxx:82
 RooSuperCategory.cxx:83
 RooSuperCategory.cxx:84
 RooSuperCategory.cxx:85
 RooSuperCategory.cxx:86
 RooSuperCategory.cxx:87
 RooSuperCategory.cxx:88
 RooSuperCategory.cxx:89
 RooSuperCategory.cxx:90
 RooSuperCategory.cxx:91
 RooSuperCategory.cxx:92
 RooSuperCategory.cxx:93
 RooSuperCategory.cxx:94
 RooSuperCategory.cxx:95
 RooSuperCategory.cxx:96
 RooSuperCategory.cxx:97
 RooSuperCategory.cxx:98
 RooSuperCategory.cxx:99
 RooSuperCategory.cxx:100
 RooSuperCategory.cxx:101
 RooSuperCategory.cxx:102
 RooSuperCategory.cxx:103
 RooSuperCategory.cxx:104
 RooSuperCategory.cxx:105
 RooSuperCategory.cxx:106
 RooSuperCategory.cxx:107
 RooSuperCategory.cxx:108
 RooSuperCategory.cxx:109
 RooSuperCategory.cxx:110
 RooSuperCategory.cxx:111
 RooSuperCategory.cxx:112
 RooSuperCategory.cxx:113
 RooSuperCategory.cxx:114
 RooSuperCategory.cxx:115
 RooSuperCategory.cxx:116
 RooSuperCategory.cxx:117
 RooSuperCategory.cxx:118
 RooSuperCategory.cxx:119
 RooSuperCategory.cxx:120
 RooSuperCategory.cxx:121
 RooSuperCategory.cxx:122
 RooSuperCategory.cxx:123
 RooSuperCategory.cxx:124
 RooSuperCategory.cxx:125
 RooSuperCategory.cxx:126
 RooSuperCategory.cxx:127
 RooSuperCategory.cxx:128
 RooSuperCategory.cxx:129
 RooSuperCategory.cxx:130
 RooSuperCategory.cxx:131
 RooSuperCategory.cxx:132
 RooSuperCategory.cxx:133
 RooSuperCategory.cxx:134
 RooSuperCategory.cxx:135
 RooSuperCategory.cxx:136
 RooSuperCategory.cxx:137
 RooSuperCategory.cxx:138
 RooSuperCategory.cxx:139
 RooSuperCategory.cxx:140
 RooSuperCategory.cxx:141
 RooSuperCategory.cxx:142
 RooSuperCategory.cxx:143
 RooSuperCategory.cxx:144
 RooSuperCategory.cxx:145
 RooSuperCategory.cxx:146
 RooSuperCategory.cxx:147
 RooSuperCategory.cxx:148
 RooSuperCategory.cxx:149
 RooSuperCategory.cxx:150
 RooSuperCategory.cxx:151
 RooSuperCategory.cxx:152
 RooSuperCategory.cxx:153
 RooSuperCategory.cxx:154
 RooSuperCategory.cxx:155
 RooSuperCategory.cxx:156
 RooSuperCategory.cxx:157
 RooSuperCategory.cxx:158
 RooSuperCategory.cxx:159
 RooSuperCategory.cxx:160
 RooSuperCategory.cxx:161
 RooSuperCategory.cxx:162
 RooSuperCategory.cxx:163
 RooSuperCategory.cxx:164
 RooSuperCategory.cxx:165
 RooSuperCategory.cxx:166
 RooSuperCategory.cxx:167
 RooSuperCategory.cxx:168
 RooSuperCategory.cxx:169
 RooSuperCategory.cxx:170
 RooSuperCategory.cxx:171
 RooSuperCategory.cxx:172
 RooSuperCategory.cxx:173
 RooSuperCategory.cxx:174
 RooSuperCategory.cxx:175
 RooSuperCategory.cxx:176
 RooSuperCategory.cxx:177
 RooSuperCategory.cxx:178
 RooSuperCategory.cxx:179
 RooSuperCategory.cxx:180
 RooSuperCategory.cxx:181
 RooSuperCategory.cxx:182
 RooSuperCategory.cxx:183
 RooSuperCategory.cxx:184
 RooSuperCategory.cxx:185
 RooSuperCategory.cxx:186
 RooSuperCategory.cxx:187
 RooSuperCategory.cxx:188
 RooSuperCategory.cxx:189
 RooSuperCategory.cxx:190
 RooSuperCategory.cxx:191
 RooSuperCategory.cxx:192
 RooSuperCategory.cxx:193
 RooSuperCategory.cxx:194
 RooSuperCategory.cxx:195
 RooSuperCategory.cxx:196
 RooSuperCategory.cxx:197
 RooSuperCategory.cxx:198
 RooSuperCategory.cxx:199
 RooSuperCategory.cxx:200
 RooSuperCategory.cxx:201
 RooSuperCategory.cxx:202
 RooSuperCategory.cxx:203
 RooSuperCategory.cxx:204
 RooSuperCategory.cxx:205
 RooSuperCategory.cxx:206
 RooSuperCategory.cxx:207
 RooSuperCategory.cxx:208
 RooSuperCategory.cxx:209
 RooSuperCategory.cxx:210
 RooSuperCategory.cxx:211
 RooSuperCategory.cxx:212
 RooSuperCategory.cxx:213
 RooSuperCategory.cxx:214
 RooSuperCategory.cxx:215
 RooSuperCategory.cxx:216
 RooSuperCategory.cxx:217
 RooSuperCategory.cxx:218
 RooSuperCategory.cxx:219
 RooSuperCategory.cxx:220
 RooSuperCategory.cxx:221
 RooSuperCategory.cxx:222
 RooSuperCategory.cxx:223
 RooSuperCategory.cxx:224
 RooSuperCategory.cxx:225
 RooSuperCategory.cxx:226
 RooSuperCategory.cxx:227
 RooSuperCategory.cxx:228
 RooSuperCategory.cxx:229
 RooSuperCategory.cxx:230
 RooSuperCategory.cxx:231
 RooSuperCategory.cxx:232
 RooSuperCategory.cxx:233
 RooSuperCategory.cxx:234
 RooSuperCategory.cxx:235
 RooSuperCategory.cxx:236
 RooSuperCategory.cxx:237
 RooSuperCategory.cxx:238
 RooSuperCategory.cxx:239
 RooSuperCategory.cxx:240
 RooSuperCategory.cxx:241
 RooSuperCategory.cxx:242
 RooSuperCategory.cxx:243
 RooSuperCategory.cxx:244
 RooSuperCategory.cxx:245
 RooSuperCategory.cxx:246
 RooSuperCategory.cxx:247
 RooSuperCategory.cxx:248
 RooSuperCategory.cxx:249
 RooSuperCategory.cxx:250
 RooSuperCategory.cxx:251
 RooSuperCategory.cxx:252
 RooSuperCategory.cxx:253
 RooSuperCategory.cxx:254
 RooSuperCategory.cxx:255
 RooSuperCategory.cxx:256
 RooSuperCategory.cxx:257
 RooSuperCategory.cxx:258
 RooSuperCategory.cxx:259
 RooSuperCategory.cxx:260
 RooSuperCategory.cxx:261
 RooSuperCategory.cxx:262
 RooSuperCategory.cxx:263
 RooSuperCategory.cxx:264
 RooSuperCategory.cxx:265
 RooSuperCategory.cxx:266
 RooSuperCategory.cxx:267
 RooSuperCategory.cxx:268
 RooSuperCategory.cxx:269
 RooSuperCategory.cxx:270
 RooSuperCategory.cxx:271
 RooSuperCategory.cxx:272
 RooSuperCategory.cxx:273
 RooSuperCategory.cxx:274
 RooSuperCategory.cxx:275
 RooSuperCategory.cxx:276
 RooSuperCategory.cxx:277
 RooSuperCategory.cxx:278
 RooSuperCategory.cxx:279
 RooSuperCategory.cxx:280
 RooSuperCategory.cxx:281
 RooSuperCategory.cxx:282
 RooSuperCategory.cxx:283
 RooSuperCategory.cxx:284
 RooSuperCategory.cxx:285
 RooSuperCategory.cxx:286
 RooSuperCategory.cxx:287
 RooSuperCategory.cxx:288
 RooSuperCategory.cxx:289
 RooSuperCategory.cxx:290
 RooSuperCategory.cxx:291
 RooSuperCategory.cxx:292
 RooSuperCategory.cxx:293
 RooSuperCategory.cxx:294
 RooSuperCategory.cxx:295
 RooSuperCategory.cxx:296
 RooSuperCategory.cxx:297
 RooSuperCategory.cxx:298
 RooSuperCategory.cxx:299
 RooSuperCategory.cxx:300
 RooSuperCategory.cxx:301
 RooSuperCategory.cxx:302
 RooSuperCategory.cxx:303
 RooSuperCategory.cxx:304
 RooSuperCategory.cxx:305
 RooSuperCategory.cxx:306
 RooSuperCategory.cxx:307
 RooSuperCategory.cxx:308
 RooSuperCategory.cxx:309
 RooSuperCategory.cxx:310
 RooSuperCategory.cxx:311
 RooSuperCategory.cxx:312
 RooSuperCategory.cxx:313
 RooSuperCategory.cxx:314
 RooSuperCategory.cxx:315
 RooSuperCategory.cxx:316
 RooSuperCategory.cxx:317
 RooSuperCategory.cxx:318
 RooSuperCategory.cxx:319