{%- import "util.include.jinja" as util -%}
{%- set messagegroups = root.messagegroups %}
"""

{%- filter wordwrap(80) %}
This is sample code to produce events to Apache Kafka with the producer clients
contained in this project. You will still need to supply event data in the marked
placews below before the program can be run.

The script gets the configuration from the command line or uses the environment
variables. The following environment variables are recognized:

- KAFKA_PRODUCER_CONFIG: The Kafka producer configuration.
- KAFKA_TOPICS: The Kafka topics to send events to.
- FABRIC_CONNECTION_STRING: A Microsoft Fabric or Azure Event Hubs connection string.

Alternatively, you can pass the configuration as command-line arguments.

- `--producer-config`: The Kafka producer configuration.
- `--topics`: The Kafka topics to send events to.
- `-c` or `--connection-string`: The Microsoft Fabric or Azure Event Hubs connection string.

{%- endfilter %}
"""

import argparse
import os
import asyncio
import json
import uuid
from typing import Optional
from datetime import datetime
from confluent_kafka import Producer as KafkaProducer

# imports the producer clients for the message group(s)
{% for messagegroupid, messagegroup in messagegroups.items() %}
{%- set groupname = messagegroupid | pascal %}
{%- set class_name = ( groupname | strip_dots ) + "EventProducer" %}
from {{main_project_name}}.producer import {{class_name}}
{%- endfor %}

# imports for the data classes for each event
{% set messagegroups = root.messagegroups %}
{%- set imports = [] %}
{%- for messagegroupid, messagegroup in messagegroups.items() -%}
{%- set messagegroup = messagegroups[messagegroupid] -%}
{%- for messageid, message in messagegroup.messages.items() -%}
{%- set type_name = util.DeclareDataType( data_project_name, root, message ) %}
{%- if type_name != "object" %}
{%- set import_statement = "from " + (type_name | lower) + " import " + type_name | strip_namespace %}
{%- if import_statement not in imports %}
{%- set _ = imports.append(import_statement) %}
{{ import_statement }}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- endfor %}

async def main(connection_string: Optional[str], producer_config: Optional[str], topic: Optional[str]):
    """
    Main function to produce events to Apache Kafka

    Args:
        connection_string (Optional[str]): The Fabric connection string
        producer_config (Optional[str]): The Kafka producer configuration
        topic (Optional[str]): The Kafka topic to send events to
    """

    {%- for messagegroupid, messagegroup in messagegroups.items() %}
    {%- set groupname = messagegroupid | pascal %}
    {%- set class_name = ( groupname | strip_dots ) + "EventProducer" %}
    if connection_string:
        # use a connection string obtained for an Event Stream from the Microsoft Fabric portal
        # or an Azure Event Hubs connection string
        {{ class_name | snake }} = {{ class_name }}.from_connection_string(connection_string, topic, 'binary')
    else:
        # use a Kafka producer configuration provided as JSON text
        kafka_producer = KafkaProducer(json.loads(producer_config))
        {{ class_name | snake }} = {{ class_name }}(kafka_producer, topic, 'binary')

    {%- for messageid, message in messagegroup.messages.items() %}
    {%- set type_name = util.DeclareDataType( data_project_name, root, message ) %}
    {%- if type_name != "object" %}

    # ---- {{ messageid }} ----
    # TODO: Supply event data for the {{ messageid }} event
    _{{ type_name | strip_namespace | snake }} = {{ type_name | pascal | strip_namespace }}()
    {%- else %}
    _{{ type_name | strip_namespace | snake }} = {}
    {%- endif %}

    # sends the '{{ messageid }}' event to Kafka topic.
    await {{ class_name | snake }}.send_{{ messageid | dotunderscore | snake }}(
        {%- for attrname, attribute in message.envelopemetadata.items() if attribute.required and attribute.value is not defined -%}
            {%- if attrname == 'time' -%}
            _{{ attrname }} = datetime.now().isoformat(),
            {%- elif attrname == 'id' -%}
            _{{ attrname }} = str(uuid.uuid4()),
            {%- else -%}
            _{{ attrname }} = 'TODO:replace',
            {%- endif %}
        {%- endfor -%}
        {%- for attrname, attribute in message.envelopemetadata.items() if attribute.type == "uritemplate" -%}
            {%- for placeholder in attribute.value | regex_search('\\{([A-Za-z0-9_]+)\\}') %}_{{ placeholder | snake }} = 'TODO: replace me', {% endfor -%}
        {%- endfor -%}
        data = _{{ type_name | strip_namespace | snake }}
        {%- for attrname, attribute in message.envelopemetadata.items() if not attribute.required and attribute.value is not defined -%}
            , _{{ attrname }} = ''
        {%- endfor -%}
    )
    print(f"Sent '{{ messageid }}' event: {_{{ type_name | strip_namespace | snake }}.to_json()}")
    {%- endfor %}
    {%- endfor %}

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Kafka Producer")
    parser.add_argument('--producer-config', default=os.getenv('KAFKA_PRODUCER_CONFIG'), help='Kafka producer config (JSON)', required=False)
    parser.add_argument('--topics', default=os.getenv('KAFKA_TOPICS'), help='Kafka topics to send events to', required=False)
    parser.add_argument('-c|--connection-string', dest='connection_string', default=os.getenv('FABRIC_CONNECTION_STRING'), help='Fabric connection string', required=False)

    args = parser.parse_args()

    asyncio.run(main(
        args.connection_string,
        args.producer_config,
        args.topics
    ))
