"""__init__.py module for the {{plugin.name}} plugin."""
# WARNING - DO NOT EDIT - YOUR CHANGES WILL NOT BE PROTECTED.
# This file is auto-generated by the aac gen-plugin and may be overwritten.

from copy import deepcopy
from os.path import join, dirname
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 import hookimpl
from aac.execute.aac_execution_result import ExecutionResult, ExecutionStatus
from aac.execute.plugin_runner import PluginRunner
from aac.in_out.files.aac_file import AaCFile

{% set comma_joiner = joiner(", ") -%}
{% if plugin.commands | length > 0 -%}
from {{plugin.package}}.{{get_python_name(plugin.name)}}_impl import plugin_name, {% for command in plugin.commands %}{{comma_joiner()}}{{get_python_name(command.name)}}{% if command.run_before | length > 0 %}{% for before in command.run_before %}{{  comma_joiner() }}before_{{get_python_name(command.name)}}_{{get_python_name(before.command)}}{% endfor %}{% endif %}{% if command.run_after | length > 0 %}{% for after in command.run_after %}{{  comma_joiner() }}after_{{get_python_name(command.name)}}_{{get_python_name(after.command)}}{% endfor %}{% endif %}{% endfor %}
{% else %}
from {{plugin.package}}.{{get_python_name(plugin.name)}}_impl import plugin_name
{% endif %}

{%- if plugin.context_constraints | length > 0 %}{% for ctx_constraint in plugin.context_constraints %}from {{plugin.package}}.{{get_python_name(plugin.name)}}_impl import {{get_python_name(ctx_constraint.name)}}
{% endfor %}{% endif -%}

{%- if plugin.schema_constraints | length > 0 %}{% for schema_constraint in plugin.schema_constraints %}from {{plugin.package}}.{{get_python_name(plugin.name)}}_impl import {{get_python_name(schema_constraint.name)}}
{% endfor %}{% endif %}

{%- if plugin.primitive_constraints | length > 0 %}{% for primitive_constraint in plugin.primitive_constraints %}from {{plugin.package}}.{{get_python_name(plugin.name)}}_impl import {{get_python_name(primitive_constraint.name)}}
{% endfor %}{% endif -%}

{%set command_list = []%}
{% for command in plugin.commands -%}
{% if command.run_before | length > 0%}{% for run_before in command.run_before %}{%if (get_python_name(run_before.plugin), get_python_name(run_before.command)) not in command_list%}from {{get_package_from_plugin(run_before.plugin)}} import run_{{get_python_name(run_before.command)}}{% set command_list = command_list.append((get_python_name(run_before.plugin), get_python_name(run_before.command))) %}{% endif %}{% endfor %}{% endif %}
{% if command.run_after | length > 0 %}{% for run_after in command.run_after %}{%if (get_python_name(run_after.plugin), get_python_name(run_after.command)) not in command_list%}from {{get_package_from_plugin(run_after.plugin)}} import run_{{get_python_name(run_after.command)}}{% set command_list = command_list.append((get_python_name(run_after.plugin), get_python_name(run_after.command)))%}{% endif %}{% endfor %}{% endif %}
{%- endfor -%}
{{get_python_name(plugin.name)}}_aac_file_name = "{{get_python_name(plugin.name)}}.aac"

{%- for command in plugin.commands -%}
{% if command.enable_cache %}{{get_python_name(command.name)}}_cache: dict[tuple, ExecutionResult] = {}{%- endif -%}
{%- endfor -%}

{%- for command in plugin.commands %}
def run_{{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:
    """
    {{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 plugin {{command.name}} command.
    """

    {% if command.enable_cache %}
    cache_key = ({% for entry in command.input %}{{ get_python_name(entry.name) }}{% if not loop.last %}, {% endif %}{% endfor %})
    if cache_key in {{get_python_name(command.name)}}_cache:
        return {{get_python_name(command.name)}}_cache[cache_key]
    {% endif %}

    result = ExecutionResult(plugin_name, "{{command.name}}", ExecutionStatus.SUCCESS, [])

    {% if command.run_before | length > 0 %}{% for run_before in command.run_before %}{{get_python_name(command.name)}}_{{get_python_name(run_before.command)}}_result = before_{{get_python_name(command.name)}}_{{get_python_name(run_before.command)}}({% for entry in command.input %}{{ get_python_name(entry.name) }}{% if not loop.last %}, {% endif %}{% endfor %}, run_{{get_python_name(run_before.command)}})
    if not {{get_python_name(command.name)}}_{{get_python_name(run_before.command)}}_result.is_success():
        return {{get_python_name(command.name)}}_{{get_python_name(run_before.command)}}_result
    else:
        result.add_messages({{get_python_name(command.name)}}_{{get_python_name(run_before.command)}}_result.messages)
    {% endfor %}{% endif %}
    {{get_python_name(command.name)}}_result = {{get_python_name(command.name)}}({% for entry in command.input %}{{ get_python_name(entry.name) }}{% if not loop.last %}, {% endif %}{% endfor %})
    if not {{get_python_name(command.name)}}_result.is_success():
        return {{get_python_name(command.name)}}_result
    else:
        result.add_messages({{get_python_name(command.name)}}_result.messages)

    {% if command.run_after | length > 0 %}{% for run_after in command.run_after %}{{get_python_name(command.name)}}_{{get_python_name(run_after.command)}}_result = after_{{get_python_name(command.name)}}_{{get_python_name(run_after.command)}}({% for entry in command.input %}{{ get_python_name(entry.name) }}{% if not loop.last %}, {% endif %}{% endfor %}, run_{{get_python_name(run_after.command)}})
    if not {{get_python_name(command.name)}}_{{get_python_name(run_after.command)}}_result.is_success():
        return {{get_python_name(command.name)}}_{{get_python_name(run_after.command)}}_result
    else:
        result.add_messages({{get_python_name(command.name)}}_{{get_python_name(run_after.command)}}_result.messages)
    {% endfor %}{% endif %}

    {% if command.enable_cache %}
    {{get_python_name(command.name)}}_cache[cache_key] = result
    {% endif %}

    return result
{% endfor %}

{% for ctx_constraint in plugin.context_constraints %}
def run_{{get_python_name(ctx_constraint.name)}}(context: LanguageContext) -> ExecutionResult:
    """
    {{ctx_constraint.description}}

    Args:
        context (LanguageContext): The context in which the constraint is being run.

    Returns:
        The results of the execution of the plugin context constraint.
    """
    return {{get_python_name(ctx_constraint.name)}}(context)
{% endfor %}

{% for schema_constraint in plugin.schema_constraints %}
def run_{{get_python_name(schema_constraint.name)}}(instance: Any, definition: Definition, defining_schema: Any, arguments: Any) -> ExecutionResult:
    """
    {{schema_constraint.description}}

    Args:
        instance (Any): The instance to be checked.
        definition (Definition): The definition of the instance.
        defining_schema (Any): The schema that defines the instance.
        arguments (Any): The arguments to be used in the constraint.

    Returns:
        The results of the execution of the plugin schema constraint.
    """
    {% if schema_constraint.arguments | length > 0 %}
    argument_copy = deepcopy(arguments)
    args = {}
    for arg in argument_copy:
        args[arg["name"]] = arg["value"]

    return {{get_python_name(schema_constraint.name)}}(instance, definition, defining_schema, **args)
    {% else %}
    return {{get_python_name(schema_constraint.name)}}(instance, definition, defining_schema)
    {% endif %}
{% endfor %}

{% for primitive_constraint in plugin.primitive_constraints %}
def run_{{get_python_name(primitive_constraint.name)}}(value: str, type_declaration: str, arguments: Any, source: AaCFile, location: SourceLocation) -> ExecutionResult:
    """
    {{primitive_constraint.description}}

    Args:
        value (str): The value to be checked.
        type_declaration (str): The type declaration of the value.
        arguments (Any): The arguments to be used in the constraint.
        source (AaCFile): The source file of the value.
        location (SourceLocation): The location of the value in the source file.

    Returns:
        The results of the execution of the plugin primitive constraint.
    """
    {% if primitive_constraint.arguments | length > 0 %}
    argument_copy = deepcopy(arguments)
    args = {}
    for arg in argument_copy:
        args[arg["name"]] = arg["value"]

    return {{get_python_name(primitive_constraint.name)}}(value, type_declaration, source, location, **args)
    {% else %}
    return {{get_python_name(primitive_constraint.name)}}(value, type_declaration, source, location)
    {% endif %}
{% endfor %}

@hookimpl
def register_plugin() -> None:
    """
    Registers information about the plugin for use in the CLI.
    """

    active_context = LanguageContext()
    {{get_python_name(plugin.name)}}_aac_file = join(dirname(__file__), {{get_python_name(plugin.name)}}_aac_file_name)
    definitions = active_context.parse_and_load({{get_python_name(plugin.name)}}_aac_file)

    {{get_python_name(plugin.name)}}_plugin_definition = [definition for definition in definitions if definition.name == plugin_name][0]

    plugin_instance = {{get_python_name(plugin.name)}}_plugin_definition.instance
    for file_to_load in plugin_instance.definition_sources:
        active_context.parse_and_load(file_to_load)

    plugin_runner = PluginRunner(plugin_definition={{get_python_name(plugin.name)}}_plugin_definition)
    {% for command in plugin.commands %}plugin_runner.add_command_callback("{{command.name}}", run_{{get_python_name(command.name)}})
    {% endfor %}
    {% for ctx_constraint in plugin.context_constraints %}plugin_runner.add_constraint_callback("{{ctx_constraint.name}}", run_{{get_python_name(ctx_constraint.name)}})
    {% endfor %}
    {% for schema_constraint in plugin.schema_constraints %}plugin_runner.add_constraint_callback("{{schema_constraint.name}}", run_{{get_python_name(schema_constraint.name)}})
    {% endfor %}
    {% for primitive_constraint in plugin.primitive_constraints %}plugin_runner.add_constraint_callback("{{primitive_constraint.name}}", run_{{get_python_name(primitive_constraint.name)}})
    {% endfor %}

    active_context.register_plugin_runner(plugin_runner)
