#!/usr/bin/env python
# (C) 2020 OpenEye Scientific Software Inc. All rights reserved.

# TERMS FOR USE OF SAMPLE CODE The software below ("Sample Code") is
# provided to current licensees or subscribers of OpenEye products or
# SaaS offerings (each a "Customer").
# Customer is hereby permitted to use, copy, and modify the Sample Code,
# subject to these terms. OpenEye claims no rights to Customer's
# modifications. Modification of Sample Code is at Customer's sole and
# exclusive risk. Sample Code may require Customer to have a then
# current license or subscription to the applicable OpenEye offering.
# THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED.  OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT
# NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be
# liable for any damages or liability in connection with the Sample Code
# or its use.

# @/ <SNIPPET>
from openeye.oechem import (OERecord, OEMolRecord, OEField, Types,
                            OESmilesToMol, OEMol, OEWriteRecord, OEReadRecord,
                            oeifstream, oeofstream, Meta, OEFieldMeta)

# @/ <SNIPPET-SET-DATA-VALUES>
record = OERecord()
int_field = OEField("My Integer Field", Types.Int)
string_field = OEField("My String Field", Types.String)
float_field = OEField("My Float Field", Types.Float)

record.set_value(int_field, 12345)
record.set_value(string_field, "Hello World!")
record.set_value(float_field, 67.89)

value = record.get_value(string_field)
print(value)  # "Hello World!"

print(record.get_value(int_field))  # 12345
print(record.get_value(float_field))  # 67.89
# @/ </SNIPPET-SET-DATA-VALUES>

# @/ <SNIPPET-TEST-FIELDS>
print(record.has_value(int_field))  # True
record.clear_value(int_field)

# The value is cleared, but the field still exists
print(record.has_value(int_field))  # False
print(record.has_field(int_field))  # True
print(record.get_value(int_field))  # None

# Remove the field
record.delete_field(int_field)
print(record.has_field(int_field))  # False
print(record.get_value(int_field))  # None
# @/ </SNIPPET-TEST-FIELDS>

# @ <SNIPPET-OTHER-DATA>
record2 = OERecord()
mol_field = OEField("Molecule", Types.Chem.Mol)
mol = OEMol()
OESmilesToMol(mol, "c1cc[nH]c1CC2COCNC2")
record2.set_value(mol_field, mol)
print(record2.get_value(mol_field).NumAtoms())  # 12

# Now let's store another record on this one
record_field = OEField("Check this out", Types.Record)
record2.set_value(record_field, record)
# @ </SNIPPET-OTHER-DATA>

# @ <SNIPPET-RECORD-IO>
# Save our record to a file
ofs = oeofstream("MyRecord.oedb")
OEWriteRecord(ofs, record2)
ofs.close()

ifs = oeifstream("MyRecord.oedb")
new_record = OEReadRecord(ifs)
child_record = new_record.get_value(record_field)
print(child_record.has_field(float_field))  # True
print(child_record.get_value(float_field))  # 67.89
# @ </SNIPPET-RECORD-IO>

# @ <SNIPPET-MOL-RECORD>
toluene = OEMol()
OESmilesToMol(toluene, "c1ccccc1C")
mol_record = OEMolRecord()
mol_record.set_mol(toluene)  # Sets the molecule on a field named "Molecule"
print(mol_record.has_mol())  # True
better_be_toluene = mol_record.get_mol()

# Show that an OEMolRecord is just an OERecord underneath
molecule_field = mol_record.get_primary_mol_field()
normal_record = OERecord(mol_record)
print(normal_record.has_field(molecule_field))  # True
other_mol_record = OEMolRecord(normal_record)
print(other_mol_record.has_mol())  # True
# @ </SNIPPET-MOL-RECORD>

# @ <SNIPPET-CONF-RECORDS>
# Create some empty conformers
conf1 = toluene.NewConf()
conf2 = toluene.NewConf()

# We'll attach a record to each conformer
score_field = OEField("score", Types.Float)
conf1_record = mol_record.get_conf_record(conf1)
conf2_record = mol_record.get_conf_record(conf1)

# Now we put a score onto each conformer's record
conf1_record.set_value(score_field, 10.0)
mol_record.set_conf_record(conf1, conf1_record)

conf2_record.set_value(score_field, 20.0)
mol_record.set_conf_record(conf2, conf2_record)

# IMPORTANT: You must set the conformers' parent molecule on the record
# at some point after setting conformer records and before the record is
# saved. Otherwise the conformer data will be lost.
mol_record.set_mol(toluene)

# We only set a single value for each conformer, but we could have
# put any number of fields and values on each conformer's record.
print(mol_record.get_conf_record(conf2).get_value(score_field))  # 20.0
# @ </SNIPPET-CONF-RECORDS>

# @ <SNIPPET-FIELD-METADATA>
rec = OERecord()

# Write a SMILES string onto a record, and provide a hint, using
# metadata, that this string is in SMILES notation.
meta = OEFieldMeta()
meta.set_option(Meta.Hints.Chem.SMILES)
meta.set_attribute(Meta.Display.Values.Priority, 1)
smiles_field = OEField("SMILES string", Types.String, meta)
rec.set_value(smiles_field, "c1ccccc1CCOC")

meta_from_record = rec.get_field_meta("SMILES string")
print(meta_from_record.has_option(Meta.Hints.Chem.SMILES))  # True
print(meta_from_record.get_attribute(Meta.Display.Values.Priority))  # 1
# @ </SNIPPET-FIELD-METADATA>


# @ <SNIPPET-FIELD-METADATA-RELATION>
value_field = OEField("value", Types.Float)
err_meta = OEFieldMeta()
# Add an "Errors For" relationship, referencing the value_field
err_meta.add_relation(Meta.Relations.ErrorsFor, value_field)
err_field = OEField("error", Types.Float, err_meta)
rec.set_value(value_field, 46.5)
rec.set_value(err_field, 0.34)
# @ </SNIPPET-FIELD-METADATA-RELATION>
# @/ </SNIPPET>
