from typing import Optional

from chemrecon.schema.db_object import col_src
from chemrecon.schema.enums import SourceDatabase
from chemrecon.schema import Compound, MolStructure, ComposedRelation
from chemrecon.schema.entry_types.molstructure_repr import MolStructureRepr
from chemrecon.schema.relation_types_source.compound_has_structure_representation_relation import (
    CompoundHasStructureRepresentation
)
from chemrecon.schema.relation_types_procedural.molstructure_convert_relation import MolStructureConvert

class CompoundHasMolStructure(ComposedRelation[Compound, MolStructure, MolStructureRepr]):
    """ This relation gives the associated molecular structures of a compound in a standardized format.
        This relation is composed of the `CompoundHasMolStructureRepr` relation and the `MolStructureConvert`
        relations.
        So if a compound entry includes an InChI, Molfile representation of a structure, this relation gives the same
        structure in the standardized, SMILES-based format.
    """
    # Attributes
    src: SourceDatabase  #: The source database containing this structure.

    # Transitive
    rel_type_1 = CompoundHasStructureRepresentation
    rel_type_2 = MolStructureConvert
    intermediate_entrytype = MolStructureRepr

    # Database
    entrytype_name = 'Compound has MolStructure'
    _table_name = 'CompoundHasMolStructure'
    symmetric = False
    source_entrytype = Compound
    target_entrytype = MolStructure
    _attribute_columns = [
        col_src
    ]
    _index = [0]

    # Filters
    @classmethod
    def filter_intermediate(cls, e: MolStructureRepr) -> bool:
        if e.implicit:
            return False
        return True

    def __init__(
            self,
            rel_1: CompoundHasStructureRepresentation,
            rel_2: MolStructureConvert,
            intermediate: MolStructureRepr,
            recon_id_1: Optional[int] = None,
            recon_id_2: Optional[int] = None
    ):
        # Inherits src from rel1
        self.src = rel_1.src
        super().__init__(rel_1, rel_2, intermediate, recon_id_1, recon_id_2)

    def _vis_str(self) -> str:
        return f'{self.src.name}'

