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

def filter(name, value, passvalue, storevalue,
           scorename, args, fromargs, asargs,decomp, arity, infile, minmax="", comp=""):
    cname= name.title().replace(' ', '')
    ucname= name.upper().replace(' ', '_') 
    lcname= name.lower().replace(' ', '_')
    return infile.replace("CLASSNAME", ucname)\
        .replace("FromClassnameArguments", fromargs)\
        .replace("ClassnameArgumentsAsArguments", asargs)\
        .replace("ClassnameArguments", args)\
        .replace("Classname", cname) \
        .replace("classname", lcname) \
        .replace("StoreValue", storevalue)\
        .replace("PassValue", passvalue) \
        .replace("Value", value) \
        .replace("MinMax", minmax)\
        .replace("MINMAX", minmax.upper())\
        .replace("minmax", minmax.lower())\
        .replace("COMPARATOR", comp)\
        .replace("Groupname", scorename) \
        .replace("GROUPNAME", scorename.upper()) \
        .replace("DecomposeArguments", decomp)\
        .replace("Arity", str(arity))\
        .replace("groupname", scorename.lower())


def make_one(name, value, passvalue, storevalue, multi, args, fromargs, asargs, decomp, arity):
    path= os.getcwd()+"/"
    cname= name.title().replace(' ', '')
    lcvalue= value.lower().replace(' ', '_').replace('*','')
    lcname= multi.lower().replace(' ', '_')

    print "Creating class "+cname + "Container"
    
  

    for p in (("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/"+multi + "sRestraint.h",
               path+"/tools/container_templates/restraint.hpp"),
              ("modules/container/src/"+multi + "sRestraint.cpp",
               path+"/tools/container_templates/restraint.cc"),
              ("modules/core/include/internal/Core"+multi + "sRestraint.h",
               path+"/tools/container_templates/corerestraint.hpp"),
              ("modules/core/src/internal/Core"+multi + "sRestraint.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/"+multi + "ContainerSet.h",
               path+"/tools/container_templates/set.hpp"),
              ("modules/container/src/"+multi + "ContainerSet.cpp",
               path+"/tools/container_templates/set.cc"),
              ("modules/container/include/"+multi + "sConstraint.h",
               path+"/tools/container_templates/state.hpp"),
              ("modules/container/src/"+multi + "sConstraint.cpp",
               path+"/tools/container_templates/state.cc"),

              ("modules/container/include/"+multi + "sOptimizerState.h",
               path+"/tools/container_templates/ostate.hpp"),
              ("modules/container/src/"+multi + "sOptimizerState.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"),


              ("modules/container/test/test_"+cname + "_restraint.py",
               path+"/tools/container_templates/test.py"),
              ("modules/container/test/test_"+cname + "_state.py",
               path+"/tools/container_templates/test_state.py"),
              ):
        ofile= open(p[0], 'w')
        ifile= open(p[1], 'r')
        contents= ifile.read()
        print "writing " + p[0]
        if len(p) > 2:
            ofile.write(filter(name, value, passvalue, storevalue, multi, args, fromargs, asargs, decomp, arity, contents, minmax=p[2], comp=p[3]))
        else:
            ofile.write(filter(name, value, passvalue, storevalue, multi, args, fromargs, asargs, decomp, arity, contents))

def main():
    make_one("particle", "Particle*", "Particle*", "Pointer<Particle>",
             "Singleton", "Particle *a", "a", "a", "v",1)
    make_one("particle pair", "ParticlePair", "const ParticlePair&", "ParticlePair",
             "Pair", "Particle *a, Particle *b",
             "ParticlePair(a,b)", "a,b", "v[0], v[1]",2)
    make_one("particle triplet", "ParticleTriplet", "const ParticleTriplet&", "ParticleTriplet",
             "Triplet", "Particle *a, Particle *b, Particle *c",
             "ParticleTriplet(a,b,c)", "a,b,c", "v[0], v[1], v[2]",3)
    make_one("particle quad", "ParticleQuad", "const ParticleQuad&", "ParticleQuad",
             "Quad", "Particle *a, Particle *b, Particle *c, Particle *d",
             "ParticleQuad(a,b,c,d)", "a,b,c,d", "v[0], v[1], v[2], v[3]",4)

  


if __name__ == '__main__':
    main()
