#!/usr/bin/env amspython
from scm.plams import *
from scm.plams.recipes.redox import AMSRedoxScreeningJob, AMSRedoxDirectJob, AMSRedoxThermodynamicCycleJob


def main():
    mol = from_smiles("C1=CC(=O)C=CC1=O", forcefield="uff")  # benzoquinone
    solvent_name = "Water"  # Solvent for AMSRedoxDirectJob and AMSRedoxThermodynamicCycleJob. See the ADF Solvation documentation for which solvents are available.
    solvent_coskf = CRSJob.database() + "/Water.coskf"  # .coskf file or AMSRedoxScreeningJob

    vibrations = True  # set to False to turn off vibrations for AMSRedoxDirectJob and AMSRedoxThermodynamicCycleJob
    reduction = True
    oxidation = True  # not really relevant for benzoquinone, set to False to not calculate

    # DFT settings for AMSRedoxDirectJob and AMSRedoxThermodynamicCycleJob
    # Note: These are for demonstration purposes only. Use a better functional/settings for production purposes.
    s = Settings()
    s.input.adf.basis.type = "DZP"
    s.input.adf.xc.gga = "PBE"
    s.input.ams.GeometryOptimization.Convergence.Quality = "Basic"

    jobs = [
        AMSRedoxScreeningJob(
            name="quick_screening", molecule=mol, reduction=reduction, oxidation=oxidation, solvent_coskf=solvent_coskf
        ),
        AMSRedoxDirectJob(
            name="direct_best_method",
            molecule=mol,
            settings=s,
            reduction=reduction,
            oxidation=oxidation,
            vibrations=vibrations,
            solvent=solvent_name,
        ),
        AMSRedoxThermodynamicCycleJob(
            name="thermodynamic_cycle",
            molecule=mol,
            settings=s,
            reduction=reduction,
            oxidation=oxidation,
            vibrations=vibrations,
            solvent=solvent_name,
        ),
    ]

    for job in jobs:
        job.run()
        print_results([job])

    print("Final summary:")
    print_results(jobs)


def print_results(jobs):
    SHE = 4.42  # standard hydrogen electrode in eV on absolute scale

    print("The experimental reduction potential of benzoquinone is +0.10 V vs. SHE")
    print(
        "{:24s} {:24s} {:24s} {:24s} {:24s}".format(
            "Jobname", "Eox(vib,rel-to-SHE)[V]", "Ered(vib,rel-to-SHE)[V]", "Eox(rel-to-SHE)[V]", "Ered(rel-to-SHE)[V]"
        )
    )

    for job in jobs:
        s = f"{job.name:24s}"
        for vibrations in [True, False]:
            try:
                Eox = job.results.get_oxidation_potential(vibrations=vibrations) - SHE
                Eox = f"{Eox:.2f}"
            except:
                Eox = "N/A"
            s += f" {Eox:24s}"

            try:
                Ered = job.results.get_reduction_potential(vibrations=vibrations) - SHE
                Ered = f"{Ered:.2f}"
            except:
                Ered = "N/A"
            s += f" {Ered:24s}"

        print(s)


if __name__ == "__main__":
    init()
    main()
    finish()
