/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 *    File: $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)             *
 *****************************************************************************/

#ifndef ROO_SIM_WS_TOOL_HH
#define ROO_SIM_WS_TOOL_HH

#include "Rtypes.h"
#include "RooWorkspace.h"
#include "RooCmdArg.h"
#include "RooFactoryWSTool.h"
#include <list>
#include <map>
#include <string>

class RooAbsCategoryLValue ; 
class RooAbsCategory ;
class RooAbsArg ;
class RooAbsPdf ;
class RooCatType ;
class RooSimultaneous ;


class RooSimWSTool : public TNamed, public RooPrintable {

public:

  // Constructors, assignment etc
  RooSimWSTool(RooWorkspace& ws) ;
  virtual ~RooSimWSTool() ;

  class BuildConfig ;
  class MultiBuildConfig ;
  class SplitRule ;
  
  class ObjBuildConfig ;
  class ObjSplitRule ;
  
  RooSimultaneous* build(const char* simPdfName, const char* protoPdfName, 
			 const RooCmdArg& arg1=RooCmdArg::none(),const RooCmdArg& arg2=RooCmdArg::none(),
			 const RooCmdArg& arg3=RooCmdArg::none(),const RooCmdArg& arg4=RooCmdArg::none(),
			 const RooCmdArg& arg5=RooCmdArg::none(),const RooCmdArg& arg6=RooCmdArg::none()) ;

  RooSimultaneous* build(const char* simPdfName,BuildConfig& bc, Bool_t verbose=kTRUE) ;

  class SimWSIFace : public RooFactoryWSTool::IFace {
  public:
    virtual ~SimWSIFace() {} ;
    std::string create(RooFactoryWSTool& ft, const char* typeName, const char* instanceName, std::vector<std::string> args) ;
  } ;

  
protected:

  RooSimWSTool(const RooSimWSTool&) ;

  ObjBuildConfig* validateConfig(BuildConfig& bc) ;
  RooSimultaneous* executeBuild(const char* simPdfName,ObjBuildConfig& obc, Bool_t verbose=kTRUE) ;
  std::string makeSplitName(const RooArgSet& splitCatSet) ;

  RooWorkspace* _ws ;

  ClassDef(RooSimWSTool,0) // Workspace oriented tool for customized cloning of p.d.f. into a simultaneous p.d.f
} ;


class RooSimWSTool::SplitRule : public TNamed {
public:
   SplitRule(const char* pdfName="") : TNamed(pdfName,pdfName) {} ;
   virtual ~SplitRule() {} ;
   void splitParameter(const char* paramList, const char* categoryList) ;
   void splitParameterConstrained(const char* paramNameList, const char* categoryNameList, const char* remainderStateName) ;
   
protected:
   
   friend class RooSimWSTool ;
   friend class BuildConfig ;
   friend class MultiBuildConfig ;
   void configure(const RooCmdArg& arg1=RooCmdArg::none(),const RooCmdArg& arg2=RooCmdArg::none(),
                  const RooCmdArg& arg3=RooCmdArg::none(),const RooCmdArg& arg4=RooCmdArg::none(),
                  const RooCmdArg& arg5=RooCmdArg::none(),const RooCmdArg& arg6=RooCmdArg::none()) ;
   
   std::list<std::string>                                             _miStateNameList ;
   std::map<std::string, std::pair<std::list<std::string>,std::string> > _paramSplitMap  ; //<paramName,<std::list<splitCatSet>,remainderStateName>>
   ClassDef(SplitRule,0) // Split rule specification for prototype p.d.f
} ;


class RooSimWSTool::BuildConfig
{
 public:
  BuildConfig(const char* pdfName, SplitRule& sr) ;
  BuildConfig(const char* pdfName, const RooCmdArg& arg1=RooCmdArg::none(),const RooCmdArg& arg2=RooCmdArg::none(),
	      const RooCmdArg& arg3=RooCmdArg::none(),const RooCmdArg& arg4=RooCmdArg::none(),
	      const RooCmdArg& arg5=RooCmdArg::none(),const RooCmdArg& arg6=RooCmdArg::none()) ;

  BuildConfig(const RooArgSet& legacyBuildConfig) ;

  virtual ~BuildConfig() {} ;
  void restrictBuild(const char* catName, const char* stateList) ;

 protected:
  BuildConfig() {} ;
  friend class RooSimWSTool ;
  std::string _masterCatName ;
  std::map<std::string,SplitRule> _pdfmap ;
  std::map<std::string,std::string> _restr ;
  RooCmdArg _conflProtocol ;

  void internalAddPdf(const char* pdfName, const char* miStateList, SplitRule& sr) ;

  ClassDef(BuildConfig,0) // Build configuration object for RooSimWSTool
 } ;


class RooSimWSTool::MultiBuildConfig : public RooSimWSTool::BuildConfig
{
 public:
  MultiBuildConfig(const char* masterIndexCat)  ;
  virtual ~MultiBuildConfig() {} ;
  void addPdf(const char* miStateList, const char* pdfName, SplitRule& sr) ;
  void addPdf(const char* miStateList, const char* pdfName, 
	      const RooCmdArg& arg1=RooCmdArg::none(),const RooCmdArg& arg2=RooCmdArg::none(),
	      const RooCmdArg& arg3=RooCmdArg::none(),const RooCmdArg& arg4=RooCmdArg::none(),
	      const RooCmdArg& arg5=RooCmdArg::none(),const RooCmdArg& arg6=RooCmdArg::none()) ;

 protected:
  friend class RooSimWSTool ;

  ClassDef(MultiBuildConfig,0) // Build configuration object for RooSimWSTool with multiple prototype p.d.f.
 } ;


  



class RooSimWSTool::ObjSplitRule {
public:
  ObjSplitRule() {} ;  
  virtual ~ObjSplitRule() ;  
  
protected:
  friend class RooSimWSTool ;
  friend class RooSimWSTool::ObjBuildConfig ;
  std::list<const RooCatType*>                            _miStateList ; 
  std::map<RooAbsArg*, std::pair<RooArgSet,std::string> > _paramSplitMap  ; //<paramName,<std::list<splitCatSet>,remainderStateName>>
  ClassDef(ObjSplitRule,0) // Validated RooSimWSTool split rule
 } ;


class RooSimWSTool::ObjBuildConfig
{
 public:
  ObjBuildConfig() : _masterCat(0) {} ;
  virtual ~ObjBuildConfig() {} ;
  void print() ;

 protected:
  friend class RooSimWSTool ;
  std::map<RooAbsPdf*,ObjSplitRule> _pdfmap ;
  std::map<RooAbsCategory*,std::list<const RooCatType*> > _restr ;
  RooCategory* _masterCat ;
  RooArgSet    _usedSplitCats ;
  RooCmdArg _conflProtocol ;

  ClassDef(ObjBuildConfig,0) // Validated RooSimWSTool build configuration
 } ;

#endif
 RooSimWSTool.h:1
 RooSimWSTool.h:2
 RooSimWSTool.h:3
 RooSimWSTool.h:4
 RooSimWSTool.h:5
 RooSimWSTool.h:6
 RooSimWSTool.h:7
 RooSimWSTool.h:8
 RooSimWSTool.h:9
 RooSimWSTool.h:10
 RooSimWSTool.h:11
 RooSimWSTool.h:12
 RooSimWSTool.h:13
 RooSimWSTool.h:14
 RooSimWSTool.h:15
 RooSimWSTool.h:16
 RooSimWSTool.h:17
 RooSimWSTool.h:18
 RooSimWSTool.h:19
 RooSimWSTool.h:20
 RooSimWSTool.h:21
 RooSimWSTool.h:22
 RooSimWSTool.h:23
 RooSimWSTool.h:24
 RooSimWSTool.h:25
 RooSimWSTool.h:26
 RooSimWSTool.h:27
 RooSimWSTool.h:28
 RooSimWSTool.h:29
 RooSimWSTool.h:30
 RooSimWSTool.h:31
 RooSimWSTool.h:32
 RooSimWSTool.h:33
 RooSimWSTool.h:34
 RooSimWSTool.h:35
 RooSimWSTool.h:36
 RooSimWSTool.h:37
 RooSimWSTool.h:38
 RooSimWSTool.h:39
 RooSimWSTool.h:40
 RooSimWSTool.h:41
 RooSimWSTool.h:42
 RooSimWSTool.h:43
 RooSimWSTool.h:44
 RooSimWSTool.h:45
 RooSimWSTool.h:46
 RooSimWSTool.h:47
 RooSimWSTool.h:48
 RooSimWSTool.h:49
 RooSimWSTool.h:50
 RooSimWSTool.h:51
 RooSimWSTool.h:52
 RooSimWSTool.h:53
 RooSimWSTool.h:54
 RooSimWSTool.h:55
 RooSimWSTool.h:56
 RooSimWSTool.h:57
 RooSimWSTool.h:58
 RooSimWSTool.h:59
 RooSimWSTool.h:60
 RooSimWSTool.h:61
 RooSimWSTool.h:62
 RooSimWSTool.h:63
 RooSimWSTool.h:64
 RooSimWSTool.h:65
 RooSimWSTool.h:66
 RooSimWSTool.h:67
 RooSimWSTool.h:68
 RooSimWSTool.h:69
 RooSimWSTool.h:70
 RooSimWSTool.h:71
 RooSimWSTool.h:72
 RooSimWSTool.h:73
 RooSimWSTool.h:74
 RooSimWSTool.h:75
 RooSimWSTool.h:76
 RooSimWSTool.h:77
 RooSimWSTool.h:78
 RooSimWSTool.h:79
 RooSimWSTool.h:80
 RooSimWSTool.h:81
 RooSimWSTool.h:82
 RooSimWSTool.h:83
 RooSimWSTool.h:84
 RooSimWSTool.h:85
 RooSimWSTool.h:86
 RooSimWSTool.h:87
 RooSimWSTool.h:88
 RooSimWSTool.h:89
 RooSimWSTool.h:90
 RooSimWSTool.h:91
 RooSimWSTool.h:92
 RooSimWSTool.h:93
 RooSimWSTool.h:94
 RooSimWSTool.h:95
 RooSimWSTool.h:96
 RooSimWSTool.h:97
 RooSimWSTool.h:98
 RooSimWSTool.h:99
 RooSimWSTool.h:100
 RooSimWSTool.h:101
 RooSimWSTool.h:102
 RooSimWSTool.h:103
 RooSimWSTool.h:104
 RooSimWSTool.h:105
 RooSimWSTool.h:106
 RooSimWSTool.h:107
 RooSimWSTool.h:108
 RooSimWSTool.h:109
 RooSimWSTool.h:110
 RooSimWSTool.h:111
 RooSimWSTool.h:112
 RooSimWSTool.h:113
 RooSimWSTool.h:114
 RooSimWSTool.h:115
 RooSimWSTool.h:116
 RooSimWSTool.h:117
 RooSimWSTool.h:118
 RooSimWSTool.h:119
 RooSimWSTool.h:120
 RooSimWSTool.h:121
 RooSimWSTool.h:122
 RooSimWSTool.h:123
 RooSimWSTool.h:124
 RooSimWSTool.h:125
 RooSimWSTool.h:126
 RooSimWSTool.h:127
 RooSimWSTool.h:128
 RooSimWSTool.h:129
 RooSimWSTool.h:130
 RooSimWSTool.h:131
 RooSimWSTool.h:132
 RooSimWSTool.h:133
 RooSimWSTool.h:134
 RooSimWSTool.h:135
 RooSimWSTool.h:136
 RooSimWSTool.h:137
 RooSimWSTool.h:138
 RooSimWSTool.h:139
 RooSimWSTool.h:140
 RooSimWSTool.h:141
 RooSimWSTool.h:142
 RooSimWSTool.h:143
 RooSimWSTool.h:144
 RooSimWSTool.h:145
 RooSimWSTool.h:146
 RooSimWSTool.h:147
 RooSimWSTool.h:148
 RooSimWSTool.h:149
 RooSimWSTool.h:150
 RooSimWSTool.h:151
 RooSimWSTool.h:152
 RooSimWSTool.h:153
 RooSimWSTool.h:154
 RooSimWSTool.h:155
 RooSimWSTool.h:156
 RooSimWSTool.h:157
 RooSimWSTool.h:158
 RooSimWSTool.h:159
 RooSimWSTool.h:160
 RooSimWSTool.h:161
 RooSimWSTool.h:162
 RooSimWSTool.h:163
 RooSimWSTool.h:164
 RooSimWSTool.h:165
 RooSimWSTool.h:166
 RooSimWSTool.h:167
 RooSimWSTool.h:168
 RooSimWSTool.h:169
 RooSimWSTool.h:170
 RooSimWSTool.h:171
 RooSimWSTool.h:172
 RooSimWSTool.h:173
 RooSimWSTool.h:174
 RooSimWSTool.h:175
 RooSimWSTool.h:176
 RooSimWSTool.h:177
 RooSimWSTool.h:178
 RooSimWSTool.h:179
 RooSimWSTool.h:180
 RooSimWSTool.h:181
 RooSimWSTool.h:182