/*****************************************************************************
 * 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)             *
 *****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// RooCintUtils is a namespace containing utility functions related 
// to CINT interfacing
//

#include "RooFit.h"

#include "RooCintUtils.h"

#include "RooMsgService.h"
#include "TInterpreter.h"

#include <string.h>
#include <string>
#include <iostream>

using namespace std ;


namespace RooCintUtils 
{

  pair<list<string>,unsigned int> ctorArgs(const char* classname, UInt_t nMinArg) 
  {
    // Utility function for RooFactoryWSTool. Return arguments of 'first' non-default, non-copy constructor of any RooAbsArg
    // derived class. Only constructors that start with two 'const char*' arguments (for name and title) are considered
    // The returned object contains 

    Int_t nreq(0) ;
    list<string> ret ;
    
    ClassInfo_t* cls = gInterpreter->ClassInfo_Factory(classname);
    MethodInfo_t* func = gInterpreter->MethodInfo_Factory(cls);
    while(gInterpreter->MethodInfo_Next(func)) {
      ret.clear() ;
      nreq=0 ;
      
      // Find 'the' constructor
      
      // Skip non-public methods
      if (!(gInterpreter->MethodInfo_Property(func) & kIsPublic)) {
	continue ;
      }	
      
      // Return type must be class name
      if (string(classname) != gInterpreter->MethodInfo_TypeName(func)) {
	continue ;
      }
      
      // Skip default constructor
      int nargs = gInterpreter->MethodInfo_NArg(func);
      if (nargs==0 || nargs==gInterpreter->MethodInfo_NDefaultArg(func)) {
	continue ;
      }
      
      MethodArgInfo_t* arg = gInterpreter->MethodArgInfo_Factory(func);
      while (gInterpreter->MethodArgInfo_Next(arg)) {
        // Require that first two arguments are of type const char*
        const char* argTypeName = gInterpreter->MethodArgInfo_TypeName(arg);
        if (nreq<2 && ((string("char*") != argTypeName 
                        && !(gInterpreter->MethodArgInfo_Property(arg) & kIsConstPointer))
                       && string("const char*") != argTypeName)) {
	  continue ;
	}
	ret.push_back(argTypeName) ;
	if(!gInterpreter->MethodArgInfo_DefaultValue(arg)) nreq++ ;
      }
      gInterpreter->MethodArgInfo_Delete(arg);

      // Check that the number of required arguments is at least nMinArg
      if (ret.size()<nMinArg) {
	continue ;
      }

      break;
    }
    gInterpreter->MethodInfo_Delete(func);
    gInterpreter->ClassInfo_Delete(cls);
    return pair<list<string>,unsigned int>(ret,nreq) ;
  }


  Bool_t isEnum(const char* classname) 
  {
    // Returns true if given type is an enum
    ClassInfo_t* cls = gInterpreter->ClassInfo_Factory(classname);
    long property = gInterpreter->ClassInfo_Property(cls);
    gInterpreter->ClassInfo_Delete(cls);
    return (property&kIsEnum) ;    
  }


  Bool_t isValidEnumValue(const char* typeName, const char* value) 
  {
    // Returns true if given type is an enum
     
    // Chop type name into class name and enum name
    char buf[256] ;
    strlcpy(buf,typeName,256) ;
    char* className = strtok(buf,":") ;

    // Chop any class name prefix from value
    if (strrchr(value,':')) {
      value = strrchr(value,':')+1 ;
    }

    ClassInfo_t* cls = gInterpreter->ClassInfo_Factory(className);
    DataMemberInfo_t* dm = gInterpreter->DataMemberInfo_Factory(cls);
    while (gInterpreter->DataMemberInfo_Next(dm)) {
      // Check if this data member represents an enum value
      // there is no "const" with CLING 
      //if (string(Form("const %s",typeName))==gInterpreter->DataMemberInfo_TypeName(dm)) {  // this for 5.34
      if (string(Form("%s",typeName))==gInterpreter->DataMemberInfo_TypeName(dm)) {
	if (string(value)==gInterpreter->DataMemberInfo_Name(dm)) {
          gInterpreter->DataMemberInfo_Delete(dm);
          gInterpreter->ClassInfo_Delete(cls);
	  return kTRUE ;
	}
      }
    }
    gInterpreter->DataMemberInfo_Delete(dm);
    gInterpreter->ClassInfo_Delete(cls);
    return kFALSE ;
  }
}

Bool_t RooCintUtils::isTypeDef(const char* trueName, const char* aliasName)
{
  // Returns true if aliasName is a typedef for trueName
  TypedefInfo_t* t = gInterpreter->TypedefInfo_Factory();
  while(gInterpreter->TypedefInfo_Next(t)) {
    if (string(trueName)==gInterpreter->TypedefInfo_TrueName(t)
        && string(aliasName)==gInterpreter->TypedefInfo_Name(t)) {
      gInterpreter->TypedefInfo_Delete(t);
      return kTRUE ;
    }
  }
  gInterpreter->TypedefInfo_Delete(t);
  return kFALSE ;
}


std::string RooCintUtils::trueName(const char* aliasName) 
{
  // Returns the true type for a given typedef name.
  TypedefInfo_t* t = gInterpreter->TypedefInfo_Factory();
  while(gInterpreter->TypedefInfo_Next(t)) {
    if (string(aliasName)==gInterpreter->TypedefInfo_Name(t)) {      
      std::string ret = trueName(string(gInterpreter->TypedefInfo_TrueName(t)).c_str()) ;
      gInterpreter->TypedefInfo_Delete(t);
      return ret;
    }
  }
  gInterpreter->TypedefInfo_Delete(t);
  return string(aliasName) ;
}

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