from .buffer import RenderBuffer
from .context import HeaderContext, TemplateInstanceContext

from .render_cls_prologue import render_class_prologue


def render_template_inst_cpp(
    hctx: HeaderContext, tmpl_data: TemplateInstanceContext
) -> str:
    r = RenderBuffer()
    render_class_prologue(r, hctx)

    tmpl_params = ", ".join(tmpl_data.params)

    r.write_trim(
        f"""
        #include <rpygen/{ tmpl_data.header_name }>
        #include "{ hctx.hname }_tmpl.hpp"

        namespace rpygen {{
        
        using BindType = rpygen::bind_{ tmpl_data.full_cpp_name_identifier }<{tmpl_params}>;
        static std::unique_ptr<BindType> inst;

        { tmpl_data.binder_typename }::{ tmpl_data.binder_typename }(py::module &m, const char * clsName)
        {{
          inst = std::make_unique<BindType>(m, clsName);
        }}

        void { tmpl_data.binder_typename }::finish(const char *set_doc, const char *add_doc)
        {{
          inst->finish(set_doc, add_doc);
          inst.reset();
        }}

        }}; // namespace rpygen
    """
    )
    r.writeln()
    return r.getvalue()


def render_template_inst_hpp(hctx: HeaderContext) -> str:
    r = RenderBuffer()
    r.write_trim(
        f"""
        // This file is autogenerated. DO NOT EDIT
        #pragma once
        #include <robotpy_build.h>

        namespace rpygen {{         
    """
    )

    for tmpl_data in hctx.template_instances:
        r.writeln()
        r.write_trim(
            f"""
            struct {tmpl_data.binder_typename} {{
              {tmpl_data.binder_typename}(py::module &m, const char * clsName);
              void finish(const char *set_doc, const char *add_doc);
            }};
        """
        )

    r.writeln("\n}; // namespace rpygen")
    return r.getvalue()
