from datafinder.typed_attributes import *
from datafinder import QueryRunnerBase, DataFrame
from model.relational import Column, Table, NoOperation, JoinOperation
from model.milestoning import ProcessingTemporalColumns, SingleBusinessDateColumn, MilestonedTable

{% for rpm in rcm.property_mappings %}
{% if not is_primitive(rpm.property) %}from {{rpm.property.name.lower()}}_finder import {{rpm.property.type.name}}RelatedFinder
{% endif %}
{% endfor %}


class {{rcm.clazz.name}}Finder:
{% if rcm.clazz.tagged_values['doc'] %}
    """{{rcm.clazz.tagged_values['doc'].value}}
    """
{% endif %}

{% if rcm.milestone_mapping %}
{% if has_processing_temporal(rcm.milestone_mapping) %}
    __zz_milestoning_columns = ProcessingTemporalColumns(Column('{{rcm.milestone_mapping._in.target.name}}', '{{rcm.milestone_mapping._in.target.type}}'),
                                                         Column('{{rcm.milestone_mapping._out.target.name}}', '{{rcm.milestone_mapping._out.target.type}}'))
{% elif has_uni_business_temporal(rcm.milestone_mapping) %}
    __zz_milestoning_columns = SingleBusinessDateColumn(Column('{{rcm.milestone_mapping._date.target.name}}', '{{rcm.milestone_mapping._date.target.type}}'))
{% endif %}
    __table = MilestonedTable('{{rcm.property_mappings[0].target.table.name}}', [], __zz_milestoning_columns)
{% else %}
    __table = Table('{{rcm.property_mappings[0].target.table.name}}', [])
{% endif %}

{% for rpm in rcm.property_mappings %}
{% if is_primitive(rpm.property) %}
    __{{rpm.property.name}} = {{rpm.property.type.name}}Attribute('{{display_name(rpm.property.name)}}', '{{rpm.target.name}}', '{{rpm.target.type}}', '{{rpm.target.table.name}}')
{% endif %}
{% endfor %}
{% for rpm in rcm.property_mappings %}
{% if not is_primitive(rpm.property) %}
    __{{rpm.property.name}} = {{rpm.property.type.name}}RelatedFinder('{{rpm.property.name}}', Column('{{rpm.target.lhs.name}}', '{{rpm.target.lhs.type}}', '{{rpm.target.lhs.table.name}}'),Column('{{rpm.target.rhs.name}}', '{{rpm.target.rhs.type}}', '{{rpm.target.rhs.table.name}}'))
{% endif %}
{% endfor %}

{% for rpm in rcm.property_mappings %}
{% if is_primitive(rpm.property) %}
    @staticmethod
    def {{rpm.property.name}}() -> {{rpm.property.type.name}}Attribute:
{% if rpm.property.tagged_values['doc'] %}
        """{{rpm.property.tagged_values['doc'].value}}"""
{% endif %}
        return {{rcm.clazz.name}}Finder.__{{rpm.property.name}}

{% else %}
    @staticmethod
    def {{rpm.property.name}}() -> {{rpm.property.type.name}}RelatedFinder:
{% if rpm.property.tagged_values['doc'] %}
        """{{rpm.property.tagged_values['doc'].value}}"""
{% endif %}
        return {{rcm.clazz.name}}Finder.__{{rpm.property.name}}

{% endif %}
{% endfor %}
    @staticmethod
{% if rcm.milestone_mapping %}
{% if has_processing_temporal(rcm.milestone_mapping) %}
    def find_all(processing_valid_at: datetime.datetime,
                 display_columns: list[Attribute],
                 filter_op: Operation = NoOperation()) -> DataFrame:
        return QueryRunnerBase.get_runner().select(None, processing_valid_at, display_columns, {{rcm.clazz.name}}Finder.__table, filter_op)
{% elif has_uni_business_temporal(rcm.milestone_mapping) %}
    def find_all(business_date: datetime.date,
                 processing_valid_at: datetime.datetime,
                 display_columns: list[Attribute],
                 filter_op: Operation = NoOperation()) -> DataFrame:
        return QueryRunnerBase.get_runner().select(business_date, processing_valid_at, display_columns, {{rcm.clazz.name}}Finder.__table, filter_op)
{% endif %}
{% else %}
    def find_all(display_columns: list[Attribute],
                 filter_op: Operation = NoOperation()) -> DataFrame:
        return QueryRunnerBase.get_runner().select(None, None, display_columns, {{rcm.clazz.name}}Finder.__table, filter_op)
{% endif %}

class {{rcm.clazz.name}}RelatedFinder:

{% if rcm.milestone_mapping %}
{% if has_processing_temporal(rcm.milestone_mapping) %}
    __zz_milestoning_columns = ProcessingTemporalColumns(Column('{{rcm.milestone_mapping._in.target.name}}', '{{rcm.milestone_mapping._in.target.type}}'),
                                                         Column('{{rcm.milestone_mapping._out.target.name}}', '{{rcm.milestone_mapping._out.target.type}}'))
{% elif has_uni_business_temporal(rcm.milestone_mapping) %}
    __zz_milestoning_columns = SingleBusinessDateColumn(Column('{{rcm.milestone_mapping._date.target.name}}', '{{rcm.milestone_mapping._date.target.type}}'))
{% endif %}
    __table = MilestonedTable('{{rcm.property_mappings[0].target.table.name}}', [], __zz_milestoning_columns)
{% else %}
    __table = Table('{{rcm.property_mappings[0].target.table.name}}', [])
{% endif %}

    def __init__(self, relation_name:str, source: Column, target: Column):
        join = JoinOperation(relation_name, {{rcm.clazz.name}}RelatedFinder.__table, source, target)
{% for rpm in rcm.property_mappings %}
{% if is_primitive(rpm.property) %}
        self.__{{rpm.property.name}} = {{rpm.property.type.name}}Attribute(relation_name.title() + ' {{display_name(rpm.property.name)}}', '{{rpm.target.name}}', '{{rpm.target.type}}', '{{rpm.target.table.name}}', join)
{% endif %}
{% endfor %}
{% for rpm in rcm.property_mappings %}
{% if not is_primitive(rpm.property) %}
        self.__{{rpm.property.name}} = {{rpm.property.type.name}}RelatedFinder('{{rpm.property.name}}', Column('{{rpm.target.lhs.name}}', '{{rpm.target.lhs.type}}', '{{rpm.target.lhs.table.name}}'),Column('{{rpm.target.rhs.name}}', '{{rpm.target.rhs.type}}', '{{rpm.target.rhs.table.name}}'))
{% endif %}
{% endfor %}

{% for rpm in rcm.property_mappings %}
{% if is_primitive(rpm.property) %}
    def {{rpm.property.name}}(self) -> {{rpm.property.type.name}}Attribute:
{% if rpm.property.tagged_values['doc'] %}
        """{{rpm.property.tagged_values['doc'].value}}"""
{% endif %}
        return self.__{{rpm.property.name}}

{% else %}
    def {{rpm.property.name}}(self) -> {{rpm.property.type.name}}RelatedFinder:
{% if rpm.property.tagged_values['doc'] %}
        """{{rpm.property.tagged_values['doc'].value}}"""
{% endif %}
        return self.__{{rpm.property.name}}

{% endif %}
{% endfor %}
