# Path: metatlas/interfaces/compounds/structure_cleaning.py
# def _InitialiseNeutralisationReactions():
# def neutralizeRadicals(mol):
# def NeutraliseCharges(mol, reactions=None):
# def desalt(mol):
# def desalt_compounds_in_dataframe(x):
# def neutralize_compounds_in_dataframe(x):
# def calculate_num_radicals_in_dataframe(x):
# def calculate_formula_in_dataframe(x):
# def calculate_monoisotopic_mw_in_dataframe(x):
# def calculate_inchi_in_dataframe(x):
# def calculate_flattened_inchi_in_dataframe(x):
# def calculate_inchikey_in_dataframe(x):
# def calculate_charge_in_dataframe(x):


import functools
import logging
import ipywidgets as widgets
import matchms
import numpy as np
from rdkit import Chem
from metatlas.interfaces.compounds import structure_cleaning as cleaning
def inchi_or_smiles_to_molecule(molecule_id: str) -> Chem.rdchem.Mol:
    """Convert Inchi or smiles to rdkit Mol"""
    out = Chem.inchi.MolFromInchi(molecule_id) or Chem.MolFromSmiles(molecule_id)
    if out is None:
        raise ValueError(f"'{molecule_id}' is not a valid Inchi or smiles")
    return out


@functools.lru_cache
def inchi_or_smiles_to_inchi(molecule_id: str) -> str:
    """Inchi or smiles string to smiles string"""
    out = Chem.inchi.MolToInchi(inchi_or_smiles_to_molecule(molecule_id))
    if out is None:
        raise ValueError(f"'{molecule_id}' is not a valid Inchi or smiles")
    return out


@functools.lru_cache
def inchi_or_smiles_to_smiles(molecule_id: str) -> str:
    """Inchi or smiles string to smiles string"""
    out = Chem.MolToSmiles(inchi_or_smiles_to_molecule(molecule_id))
    if out is None:
        raise ValueError(f"'{molecule_id}' is not a valid Inchi or smiles")
    return out


@functools.lru_cache
def normalize_molecule(mol: Chem.rdchem.Mol) -> Chem.rdchem.Mol:
    """Removes salt and neutralizes charges"""
    desalted, _ = cleaning.desalt(mol)

# Path: metatlas/interfaces/compounds/structure_cleaning.py
# def _InitialiseNeutralisationReactions():
# def neutralizeRadicals(mol):
# def NeutraliseCharges(mol, reactions=None):
# def desalt(mol):
# def desalt_compounds_in_dataframe(x):
# def neutralize_compounds_in_dataframe(x):
# def calculate_num_radicals_in_dataframe(x):
# def calculate_formula_in_dataframe(x):
# def calculate_monoisotopic_mw_in_dataframe(x):
# def calculate_inchi_in_dataframe(x):
# def calculate_flattened_inchi_in_dataframe(x):
# def calculate_inchikey_in_dataframe(x):
# def calculate_charge_in_dataframe(x):


# Path: metatlas/tools/cheminfo.py
import functools
import logging
import ipywidgets as widgets
import matchms
import numpy as np
from rdkit import Chem
from metatlas.interfaces.compounds import structure_cleaning as cleaning

def inchi_or_smiles_to_molecule(molecule_id: str) -> Chem.rdchem.Mol:
    """Convert Inchi or smiles to rdkit Mol"""
    out = Chem.inchi.MolFromInchi(molecule_id) or Chem.MolFromSmiles(molecule_id)
    if out is None:
        raise ValueError(f"'{molecule_id}' is not a valid Inchi or smiles")
    return out


@functools.lru_cache
def inchi_or_smiles_to_inchi(molecule_id: str) -> str:
    """Inchi or smiles string to smiles string"""
    out = Chem.inchi.MolToInchi(inchi_or_smiles_to_molecule(molecule_id))
    if out is None:
        raise ValueError(f"'{molecule_id}' is not a valid Inchi or smiles")
    return out


@functools.lru_cache
def inchi_or_smiles_to_smiles(molecule_id: str) -> str:
    """Inchi or smiles string to smiles string"""
    out = Chem.MolToSmiles(inchi_or_smiles_to_molecule(molecule_id))
    if out is None:
        raise ValueError(f"'{molecule_id}' is not a valid Inchi or smiles")
    return out


@functools.lru_cache
def normalize_molecule(mol: Chem.rdchem.Mol) -> Chem.rdchem.Mol:
    """Removes salt and neutralizes charges"""
    desalted, _ = cleaning.desalt(mol)

    return cleaning.NeutraliseCharges(desalted)[0]