import os
import sys
sys.path.append(os.path.normpath(os.path.join(os.path.abspath(__file__), '..', '..', '..', "common")))
from env_indigo import *

indigo = Indigo()
def testAutomap1 ():
    print("*** Simple test 1 ***")
    rxn1 = indigo.loadReaction("CC1=CSC(C=C(N=[N+]=[N-])C(OCC)=O)=C1>>CC1=CSC2=C1NC(C(OCC)=O)=C2")
    rxn1.automap("discard")
    print(rxn1.smiles())
    
def testAutomap2 ():
    print("*** Simple test 2 ***")
    rxn = indigo.createReaction()
    rxn.addProduct(indigo.loadMolecule("C(CC1=CC=CC=C1)C1=CC=C(S1)C=O"))
    rxn.addReactant(indigo.loadMolecule("C1(=CC=CC=C1)C#CC1=CC=C(S1)C=O"))
    rxn.addReactant(indigo.loadMolecule("C(CC1=CC=CC=C1)C=1C=C(SC1)C=O"))
    rxn.automap("discard") 
    print(rxn.smiles())
    
def testAutomap3 ():
    print("*** Test reaction with single atom component mapping ***")
    rxn = indigo.createReaction()
    rxn.addReactant(indigo.loadMolecule("CC(OC)=O"))
    rxn.addReactant(indigo.loadMolecule("[Na+].[OH-]"))
    rxn.addProduct(indigo.loadMolecule("CC(O)=O"))
    rxn.addProduct(indigo.loadMolecule("C[O-].[Na+]"))
    rxn.automap("discard") 
    print(rxn.smiles())
    
def testAutomap4 ():
    print("*** Testing foldHydrogens with automap ***")
    reaction = indigo.createReaction()
    reaction.addProduct(indigo.loadMolecule("O=C1CCC[C@]2([H])C3C=CC(C3)[C@@]21[H]"))
    reaction.addReactant(indigo.loadMolecule("C1C=CC=C1"))
    reaction.addReactant(indigo.loadMolecule("O=C1CCCC=C1"))
    print(reaction.smiles())
    reaction.foldHydrogens() # if folding is turned on then there is an a error in automap
    print(reaction.smiles())
    reaction.automap("discard")
    print(reaction.smiles())
  
def testAutomap5 ():
    print("*** Test reaction with single atoms***")
    rxn = indigo.createReaction()
    rxn.addReactant(indigo.loadMolecule("CC(OC)=O"))
    rxn.addReactant(indigo.loadMolecule("[Na+]"))
    rxn.addProduct(indigo.loadMolecule("CC(O)=O"))
    rxn.addProduct(indigo.loadMolecule("[Na+]"))
    rxn.automap("discard")
    print(rxn.smiles())
    
def testAutomap6 ():
    print("*** Test query reaction ***")
    qr = indigo.loadQueryReaction("C1=CC=CC=C1>>C1=CC=CC(CC2=CC=CC=C2)=C1")
    qr.automap("discard")
    print(qr.smiles())
    
def testAutomap (testname, reactants, products, mode="discard"):
    print("*** %s ***" % testname)
    rxn = indigo.createReaction()
    for r in reactants:
        rxn.addReactant(indigo.loadMolecule(r))
    for p in products:
        rxn.addProduct(indigo.loadMolecule(p))
    print("Before:")
    print(rxn.smiles())
    rxn.automap(mode)
    print("After:")
    print(rxn.smiles())

def testAutomapR (testname, rxn_s, mode="discard"):
    print("*** %s ***" % testname)
    rxn = indigo.loadReaction(rxn_s)
    print("Before:")
    print(rxn.canonicalSmiles())
    rxn.automap(mode)
    print("After:")
    print(rxn.canonicalSmiles())

def testAutomapQuery (testname, reactants, products, mode="discard"):
    print("*** %s ***" % testname)
    rxn = indigo.createQueryReaction()
    for r in reactants:
        rxn.addReactant(indigo.loadQueryMolecule(r))
    for p in products:
        rxn.addProduct(indigo.loadQueryMolecule(p))
    print("Before:")
    print(rxn.smiles())
    rxn.automap(mode)
    print("After:")
    print(rxn.smiles())
     
  
testAutomap1()
testAutomap2()
testAutomap3()
testAutomap4()
testAutomap5()
testAutomap("AAM1", [ "O=CN(C)C", "S(=O)(Cl)Cl", "OC(=O)c1ccccn1", "[OH-].[Na+]" ], [ "Cl.C(C)OC(=O)C1=NC=CC(=C1)Cl" ] )
testAutomap("AAM2", [ "S(=O)(Cl)Cl", "OC(=O)c1ccccn1", "[OH-].[Na+]", "[NH4+].[OH-]" ], [ "ClC=1C=C(N=CC1)C(=O)N" ] )
testAutomap("AAM3", [ "[H-].[Na+]", "N#Cc1ccccn1", "NC(N)=O", "S(O)(O)(=O)=O" ], [ "N1=C(C=CC=C1)C1=NC(=NC(=N1)C1=NC=CC=C1)O" ] )
testAutomap("AAM4", [ "[H-].[Na+]", "N#Cc1ccccn1", "Cl.NC(=N)N" ], [ "N1=C(C=CC=C1)C1=NC(=NC(=N1)C1=NC=CC=C1)N" ] )
testAutomap("AAM5", [ "C1CC1" ], [ "C1CCC1C" ] )
testAutomap("AAM6", [ "C1CCC1C" ], [ "C1CC1" ] )
testAutomap("D-Y-exchange1", [ "C1CC1", "C1CC1", "C1CC1" ], [ "CC(C)C", "CC(C)C", "CC(C)C" ] )
testAutomap("D-Y-exchange2", [ "C1CC1", "CC(C)C" ], [ "CC(C)C", "C1CC1" ] )
testAutomap("D-Y-exchange3", [ "C1C2C11C3CC213" ], [ "CC(C)C(C)C(C)C(C)C" ] )
testAutomap("CON1", [ "CCCC", "NNNN.OOOO" ], [ "CCCC.NNNN", "OOOO" ] )
testAutomap("CON2", [ "CCCC", "NNNN.NNNN" ], [ "CCCC", "NNNN" ] )
testAutomap("INGNORE CHARGES0", [ "CCCCC" ], [ "CC[C++]CC" ])
testAutomap("INGNORE CHARGES1", [ "CCCCC" ], [ "CC[C++]CC" ] , "discard ignore_charges")
testAutomap("INGNORE ISOTOPE0", [ "CCCCC" ], [ "CC[8CH2]CC"])
testAutomap("INGNORE ISOTOPE1", [ "CCCCC" ], [ "CC[8CH2]CC"], "discard ignore_isotopes" )
testAutomap("INGNORE VALENCE0", [ "CC[GeH2]CC" ], [ "CC[Ge]CC"])
testAutomap("INGNORE VALENCE1", [ "CC[GeH2]CC" ], [ "CC[Ge]CC"], "discard ignore_valence" )
testAutomap("INGNORE RADICAL0", [ "CCCCC" ], [ "CC[CH]CC"])
testAutomap("INGNORE RADICAL1", [ "CCCCC" ], [ "CC[CH]CC"], "discard ignore_radicals" )
testAutomap("AUTOMORPHISM KEEP ATOM DEGREE", [ "BrC1=CC=CC=C1" ], [ "C1=CC=CC=C1C1CN(CCN1)C"], "discard" )
testAutomap("AUTOMORPHISM KEEP BOND ORDER", [ "C=C1CC=C(C=C1)P(C1=CC=CC=C1)C1=CC=CC=C1" ], [ "C(NC1C=CC=C1)C1CC=C(C=C1)P(C1=CC=CC=C1)C1=CC=CC=C1"], "discard" )
testAutomap("AUTOMORPHISM KEEP ATOM NUMBER", [ "COC(C1=C(C=CC(=C1)I)O)=O", "C(C)C(C(=O)O)Br"], [ "COC(C1=C(C=CC(=C1)I)OCC(=O)OCC)=O" ],  "discard" )
testAutomap("AAM WITH DISSOCIATIONS", ["NCC(c1c2c(ccc(OC)c2)ccc1)CO", "CCN(CC)CC", "FC(F)(F)C(OC(=O)C(F)(F)F)=O"],["FC(F)(F)C(NCC(c1c2c(ccc(OC)c2)ccc1)CO)=O"], "discard")
testAutomapQuery("QUERY AAM", ["C1=CC=CC=C1"], ["C1=CC=CC(CC2=CC=CC=C2)=C1"], "discard")
testAutomapR("Keep mapping in KEEP mode",  "C1CC[NH:2]CC1.C1CC[S:1]CC1>>C1CC2CC[S:2]CC2C[NH:1]1", "KEEP")
testAutomapR("Keep mapping in ALTER mode",  "C1CC[NH:2]CC1.C1CC[S:1]CC1>>C1CC2CC[S:2]CC2C[NH:1]1", "ALTER")
testAutomapR("Keep mapping in KEEP mode for radicals",  "C[12CH2:1]C(CCCC)[CH]CCCCCCC>>C[13CH2:1]C(CCCC)[C]CCCCCCCC |^1:7,^4:22|", "KEEP")

