#!/usr/bin/python
import sys
import os

def filter((function_name, type_name, class_name, variable_type, argument_type, return_type,
            storage_type,
            plural_variable_type, plural_argument_type, plural_storage_type),
           infile, minmax="", comp=""):
    header_guard_class_name=class_name.upper()
    header_guard_minmax= minmax.upper()
    helpername= class_name.lower()
    return infile\
        .replace("MINORMAXHEADERNAME", minmax.upper())\
        .replace("HEADERNAME", class_name.upper())\
        .replace("HELPERNAME", helpername)\
        .replace("CLASSFUNCTIONNAME", helpername)\
        .replace("FUNCTIONNAME", function_name)\
        .replace("TYPENAME", type_name)\
        .replace("LCCLASSNAME", class_name.lower())\
        .replace("CLASSNAME", class_name)\
        .replace("PLURALVARIABLETYPE", plural_variable_type)\
        .replace("PLURALARGUMENTTYPE", plural_argument_type)\
        .replace("RETURNTYPE", return_type)\
        .replace("VARIABLETYPE", variable_type)\
        .replace("PLURALSTORAGETYPE", plural_storage_type)\
        .replace("MINORMAX", minmax)\
        .replace("COMPARATOR", comp)\
        .replace("ARGUMENTTYPE", argument_type)\
        .replace("STORAGETYPE", storage_type)


def make_one(params, test=True):
    (function_name, type_name, class_name, variable_type, argument_type, return_type,
     storage_type,
     plural_variable_type, plural_argument_type, plural_storage_type)= params
    path= os.getcwd()+"/"
    multi= class_name
    plural_multi= multi+"s"
    cname=function_name

    print "Creating class "+cname + "Container"
    
  

    files= [("kernel/include/"+multi + "Container.h",
               path+"tools/container_templates/container.hpp"),
              ("kernel/src/"+multi + "Container.cpp",
               path+"/tools/container_templates/container.cc"),
              ("modules/core/include/internal/"+multi.lower() + "_helpers.h",
               path+"tools/container_templates/helper.hpp"),
              ("modules/core/src/internal/"+multi.lower() + "_helpers.cpp",
               path+"tools/container_templates/helper.cc"),

              ("modules/container/include/"+plural_multi + "Restraint.h",
               path+"/tools/container_templates/restraint.hpp"),
              ("modules/container/src/"+plural_multi + "Restraint.cpp",
               path+"/tools/container_templates/restraint.cc"),
              ("modules/core/include/internal/Core"+plural_multi + "Restraint.h",
               path+"/tools/container_templates/corerestraint.hpp"),
              ("modules/core/src/internal/Core"+plural_multi + "Restraint.cpp",
               path+"/tools/container_templates/corerestraint.cc"),

              ("modules/container/include/List"+multi + "Container.h",
               path+"/tools/container_templates/list.hpp"),
              ("modules/container/src/List"+multi + "Container.cpp",
               path+"/tools/container_templates/list.cc"),
              ("modules/core/include/internal/CoreList"+multi + "Container.h",
               path+"/tools/container_templates/corelist.hpp"),
              ("modules/core/src/internal/CoreList"+multi + "Container.cpp",
               path+"/tools/container_templates/corelist.cc"),


              ("modules/core/include/"+multi + "Restraint.h",
               path+"/tools/container_templates/srestraint.hpp"),
              ("modules/core/src/"+multi + "Restraint.cpp",
               path+"/tools/container_templates/srestraint.cc"),

              ("modules/container/include/InContainer"+multi + "Filter.h",
               path+"/tools/container_templates/in_container.hpp"),
              ("modules/container/src/InContainer"+multi + "Filter.cpp",
               path+"/tools/container_templates/in_container.cc"),


              ("modules/container/include/"+multi + "ContainerSet.h",
               path+"/tools/container_templates/set.hpp"),
              ("modules/container/src/"+multi + "ContainerSet.cpp",
               path+"/tools/container_templates/set.cc"),
              ("modules/container/include/"+plural_multi + "Constraint.h",
               path+"/tools/container_templates/state.hpp"),
              ("modules/container/src/"+plural_multi + "Constraint.cpp",
               path+"/tools/container_templates/state.cc"),

              ("modules/container/include/"+plural_multi + "OptimizerState.h",
               path+"/tools/container_templates/ostate.hpp"),
              ("modules/container/src/"+plural_multi + "OptimizerState.cpp",
               path+"/tools/container_templates/ostate.cc"),

              #("modules/container/include/RemoveInactive"+multi + "sOptimizerState.h",
              # path+"/tools/container_templates/inactive.hpp"),
              #("modules/container/src/RemoveInactive"+multi + "sOptimizerState.cpp",
              # path+"/tools/container_templates/inactive.cc"),
  
              ("modules/core/include/"+multi + "Constraint.h",
               path+"/tools/container_templates/sstate.hpp"),
              ("modules/core/src/"+multi + "Constraint.cpp",
               path+"/tools/container_templates/sstate.cc"),
  
              ("kernel/include/"+multi + "Modifier.h",
               path+"/tools/container_templates/function.hpp"),
              ("kernel/src/"+multi + "Modifier.cpp",
               path+"/tools/container_templates/function.cc"),

              ("kernel/include/"+multi + "Filter.h",
               path+"/tools/container_templates/filter.hpp"),
              ("kernel/src/"+multi + "Filter.cpp",
               path+"/tools/container_templates/filter.cc"),

              ("kernel/include/"+multi + "Score.h",
               path+"/tools/container_templates/score.hpp"),
              ("kernel/src/"+multi + "Score.cpp",
               path+"/tools/container_templates/score.cc"),


              ("modules/container/include/Minimum"+multi + "Restraint.h",
               path+"/tools/container_templates/min.hpp", "Minimum", "less"),
              ("modules/container/src/Minimum"+multi + "Restraint.cpp",
               path+"/tools/container_templates/min.cc", "Minimum", "less"),
              ("modules/container/include/Maximum"+multi + "Restraint.h",
               path+"/tools/container_templates/min.hpp", "Maximum", "greater"),
              ("modules/container/src/Maximum"+multi + "Restraint.cpp",
               path+"/tools/container_templates/min.cc", "Maximum", "greater"),


              ("modules/container/include/Minimum"+multi + "Score.h",
               path+"/tools/container_templates/minscore.hpp", "Minimum", "less"),
              ("modules/container/src/Minimum"+multi + "Score.cpp",
               path+"/tools/container_templates/minscore.cc", "Minimum", "less"),
              ("modules/container/include/Maximum"+multi + "Score.h",
               path+"/tools/container_templates/minscore.hpp", "Maximum", "greater"),
              ("modules/container/src/Maximum"+multi + "Score.cpp",
               path+"/tools/container_templates/minscore.cc", "Maximum", "greater")]
    if test:
        files.append(("modules/container/test/test_"+cname + "_restraint.py",
                   path+"/tools/container_templates/test.py"))
        files.append(("modules/container/test/test_"+cname + "_state.py",
                      path+"/tools/container_templates/test_state.py"))
    for p in files:
        ofile= open(p[0], 'w')
        ifile= open(p[1], 'r')
        contents= ifile.read()
        print "writing " + p[0]
        if len(p) > 2:
            ofile.write(filter(params,
                               contents, minmax=p[2], comp=p[3]))
        else:
            ofile.write(filter(params,
                               contents))

def main():
    #(function_name, class_name, variable_type, argument_type,
    # return_type, storage_type,
    #        plural_variable_type, plural_argument_type, plural_storage_type)
    make_one(("particle", "Particle", "Singleton", "Particle*", "Particle*",
              "Particle*", "Pointer<Particle>",
              "ParticlesTemp", "ParticlesTemp", "Particles"))
    make_one(("particle_pair", "ParticlePair", "Pair", "ParticlePair", "const ParticlePair&",
              "const ParticlePair", "ParticlePair",
              "ParticlePairsTemp", "ParticlePairsTemp", "ParticlePairs"))
    make_one(("particle_triplet", "ParticleTriplet", "Triplet", "ParticleTriplet", "const ParticleTriplet&",
              "const ParticleTriplet", "ParticleTriplet",
              "ParticleTripletsTemp", "ParticleTripletsTemp", "ParticleTriplets"), test=False)
    make_one(("particle_quad", "ParticleQuad", "Quad", "ParticleQuad", "const ParticleQuad&",
              "const ParticleQuad", "ParticleQuad",
              "ParticleQuadsTemp", "ParticleQuadsTemp", "ParticleQuads"), test=False)
    #make_one("particle tuple", "ParticlesTemp", "const ParticlesTemp&", "Particles",
    #         "Tuple", "particle tuples", "ParticlesList", "Tuples", test=False)

  


if __name__ == '__main__':
    main()