"""The AaC {{plugin.name}} plugin implementation module."""
# NOTE: It is safe to edit this file.
# This file is only initially generated by aac gen-plugin, and it won't be overwritten if the file already exists.

# There may be some unused imports depending on the definition of the plugin, be sure to remove unused imports.
from typing import Any

from aac.context.definition import Definition
from aac.context.language_context import LanguageContext
from aac.context.source_location import SourceLocation
from aac.execute.aac_execution_result import ExecutionResult, ExecutionStatus, ExecutionMessage, MessageLevel
from aac.in_out.files.aac_file import AaCFile

plugin_name = "{{plugin.name}}"

{% for command in plugin.commands %}{% if command.run_before | length > 0 %}{% for run_before in command.run_before %}
def before_{{get_python_name(command.name)}}_{{get_python_name(run_before.command)}}({% for entry in command.input %}{{ get_python_name(entry.name) }}: {{get_python_type(entry.type)}}{% if not loop.last %}, {% endif %}{% endfor %}, run_{{get_python_name(run_before.command)}}) -> ExecutionResult:
    """
    Run the {{run_before.plugin}} {{run_before.command}} command before the {{command.name}} command.

    Args:
        {% for entry in command.input %}{{get_python_name(entry.name)}} ({{get_python_type(entry.type)}}): {{entry.description}}
        {%- endfor %}

   Returns:
        The results of the execution of the {{run_before.command}} command.
    """

    # TODO: configure and call the {{run_before.command}} command using {{command.name}} command inputs
    status = ExecutionStatus.GENERAL_FAILURE
    messages: list[ExecutionMessage] = []
    error_msg = ExecutionMessage("The {{run_before.plugin}} {{run_before.command}} before handling for the {{command.name}} command has not been implemented yet.", MessageLevel.ERROR, None, None)
    messages.append(error_msg)

    return ExecutionResult(plugin_name, "{{command.name}}", status, messages)
{% endfor %}{% endif %}

def {{get_python_name(command.name)}}({% for entry in command.input %}{{ get_python_name(entry.name)}}: {{get_python_type(entry.type)}}{% if not loop.last %}, {% endif %}{% endfor %}) -> ExecutionResult:
    """
    Business logic for allowing {{command.name}} command to perform {{command.help_text}}
    Args:
        {% for entry in command.input %}{{get_python_name(entry.name)}} ({{get_python_type(entry.type)}}): {{entry.description}}
        {%- endfor %}

   Returns:
        The results of the execution of the {{command.name}} command.
    """

    # TODO: implement plugin logic here
    status = ExecutionStatus.GENERAL_FAILURE
    messages: list[ExecutionMessage] = []
    error_msg = ExecutionMessage("The {{command.name}} command for the {{plugin.name}} plugin has not been implemented yet.", MessageLevel.ERROR, None, None)
    messages.append(error_msg)

    return ExecutionResult(plugin_name, "{{command.name}}", status, messages)

{% if command.run_after | length > 0 %}{% for run_after in command.run_after %}
def after_{{get_python_name(command.name)}}_{{get_python_name(run_after.command)}}({% for entry in command.input %}{{ get_python_name(entry.name) }}: {{ get_python_type(entry.type) }}{% if not loop.last %}, {% endif %}{% endfor %}, run_{{get_python_name(run_after.command)}}) -> ExecutionResult:
    """
    Run the {{run_after.plugin}} {{run_after.command}} command after the {{command.name}} command.

    Args:
        {% for entry in command.input %}{{get_python_name(entry.name)}} ({{get_python_type(entry.type)}}): {{entry.description}}
        {%- endfor %}

   Returns:
        The results of the execution of the {{run_after.command}} command.
    """

    # TODO: configure and call the {{run_after.command}} command using {{command.name}} command inputs
    status = ExecutionStatus.GENERAL_FAILURE
    messages: list[ExecutionMessage] = []
    error_msg = ExecutionMessage("The {{run_after.plugin}} {{run_after.command}} after handling for the {{command.name}} command has not been implemented yet.", MessageLevel.ERROR, None, None)
    messages.append(error_msg)

    return ExecutionResult(plugin_name, "{{command.name}}", status, messages)
    {% endfor %}{% endif %}{% endfor %}

{% if plugin.context_constraints | length > 0 %}{% for ctx_constraint in plugin.context_constraints%}
def {{get_python_name(ctx_constraint.name)}}(context: LanguageContext) -> ExecutionResult:
    """
    Business logic for the {{ctx_constraint.name}} constraint.

    Args:
        context (LanguageContext): The language_context object

   Returns:
        The results of the execution of the {{ctx_constraint.name}} command.
    """

    # TODO: rewrite the code below to implement your constraint logic
    # you will likely be evaluating definitions from the LanguageContext, so use the source and location from the definition for messages
    status = ExecutionStatus.GENERAL_FAILURE
    messages: list[ExecutionMessage] = []
    error_msg = ExecutionMessage("The {{ctx_constraint.name}} constraint for the {{plugin.name}} plugin has not been implemented yet.", MessageLevel.ERROR, None, None)
    messages.append(error_msg)

    return ExecutionResult(plugin_name, "{{ctx_constraint.name}}", status, messages)
    {% endfor%}{% endif %}

{% if plugin.schema_constraints | length > 0 %}{% for schema_constraint in plugin.schema_constraints%}
def {{get_python_name(schema_constraint.name)}}(instance: Any, definition: Definition, defining_schema: Any{% if schema_constraint.arguments | length > 0 %}, {% for entry in schema_constraint.arguments %}{{ get_python_name(entry.name) }}: {{ get_python_type(entry.type) }}{% if not loop.last %}, {% endif %}{% endfor %}{% endif %}) -> ExecutionResult:
    """
    Business logic for the {{schema_constraint.name}} constraint.

    Args:
        instance (Any): The instance to be checked.
        definition (Definition): The definition of the instance.
        defining_schema (Any): The schema that defines the instance.
        {% for entry in schema_constraint.arguments %}{{get_python_name(entry.name)}} ({{get_python_type(entry.type)}}): {{entry.description}}
        {% endfor %}

   Returns:
        The results of the execution of the {{schema_constraint.name}} command.
    """

    # TODO: rewrite the code below to implement your constraint logic
    # you can get the source and location from the definition for messages
    status = ExecutionStatus.GENERAL_FAILURE
    messages: list[ExecutionMessage] = []
    error_msg = ExecutionMessage("The {{schema_constraint.name}} constraint for the {{plugin.name}} plugin has not been implemented yet.", MessageLevel.ERROR, definition.source, None)
    messages.append(error_msg)

    return ExecutionResult(plugin_name, "{{schema_constraint.name}}", status, messages)
    {% endfor%}{% endif %}

{% if plugin.primitive_constraints | length > 0 %}{% for primitive_constraint in plugin.primitive_constraints%}
def {{get_python_name(primitive_constraint.name)}}(value: str, type_declaration: str, source: AaCFile, location: SourceLocation{% if primitive_constraint.arguments | length > 0 %}, {% for entry in primitive_constraint.arguments %}{{ get_python_name(entry.name) }}: {{ get_python_type(entry.type) }}{% if not loop.last %}, {% endif %}{% endfor %}{% endif %}) -> ExecutionResult:
    """
    Business logic for the {{primitive_constraint.name}} constraint.

    Args:
        value (str): The value to be checked.
        type_declaration (str): The type declaration of the value.
        source (AaCFile): The source file of the value.
        location (SourceLocation): The location of the value in the source file.
        {% for entry in primitive_constraint.arguments %}{{get_python_name(entry.name)}} ({{get_python_type(entry.type)}}): {{entry.description}}
        {% endfor %}

    Returns:
        The results of the execution of the {{primitive_constraint.name}} command.
"""

    # TODO: rewrite the code below to implement your constraint logic
    # the checker has provided you with source and location data for messages
    status = ExecutionStatus.GENERAL_FAILURE
    messages: list[ExecutionMessage] = []
    error_msg = ExecutionMessage("The {{primitive_constraint.name}} constraint for the {{plugin.name}} plugin has not been implemented yet.", MessageLevel.ERROR, source=source, location=location)
    messages.append(error_msg)

    return ExecutionResult(plugin_name, "{{primitive_constraint.name}}", status, messages)
    {% endfor %}{% endif %}
