﻿<#@ template language="C#" linePragmas="false" visibility = "internal" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="Microsoft.CodeAnalysis" #>
//----------------------
// <auto-generated>
//     This code was generated by a tool.
// </auto-generated>
//----------------------
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System;
using AutoGen.Core;

<#if (!String.IsNullOrEmpty(NameSpace)) {#>
namespace <#=NameSpace#>
{
<#}#>
    public partial class <#=ClassName#>
    {
<#foreach (var functionContract in FunctionContracts) {#>

        private class <#=functionContract.GetFunctionSchemaClassName()#>
        {
<#foreach (var parameter in functionContract.Parameters) {#>
<#if (parameter.IsOptional) {#>
            [JsonPropertyName(@"<#=parameter.Name#>")]
			public <#=parameter.Type#> <#=parameter.Name#> {get; set;} = <#=parameter.DefaultValue#>;
<#} else {#>
            [JsonPropertyName(@"<#=parameter.Name#>")]
			public <#=parameter.Type#> <#=parameter.Name#> {get; set;}
<#}#>
<#}#>
        }

        public <#=functionContract.ReturnType#> <#=functionContract.GetFunctionWrapperName()#>(string arguments)
        {
            var schema = JsonSerializer.Deserialize<<#=functionContract.GetFunctionSchemaClassName()#>>(
                arguments, 
                new JsonSerializerOptions
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                });
<# var argumentLists = string.Join(", ", functionContract.Parameters.Select(p => $"schema.{p.Name}")); #>

            return <#=functionContract.Name#>(<#=argumentLists#>);
        }

        public FunctionContract <#=functionContract.GetFunctionContractName()#>
        {
            get => new FunctionContract
            {
<#if (functionContract.Namespace != null) {#>
                Namespace = @"<#=functionContract.Namespace#>",
<#}#>
<#if (functionContract.ClassName != null) {#>
                ClassName = @"<#=functionContract.ClassName#>",
<#}#>
<#if (functionContract.Name != null) {#>
                Name = @"<#=functionContract.Name#>",
<#}#>
<#if (functionContract.Description != null) {#>
                Description = @"<#=functionContract.Description.Replace("\"", "\"\"")#>",
<#}#>
<#if (functionContract.ReturnType != null) {#>
                ReturnType = typeof(<#=functionContract.ReturnType#>),
<#}#>
<#if (functionContract.ReturnDescription != null) {#>
                ReturnDescription = @"<#=functionContract.ReturnDescription#>",
<#}#>
<#if (functionContract.Parameters != null) {#>
                Parameters = new global::AutoGen.Core.FunctionParameterContract[]
                {
<#foreach (var parameter in functionContract.Parameters) {#>
                    new FunctionParameterContract
                    {
<#if (parameter.Name != null) {#>
                        Name = @"<#=parameter.Name#>",
<#}#>
<#if (parameter.Description != null) {#>
                        Description = @"<#= parameter.Description.Replace("\"", "\"\"") #>",
<#}#>
<#if (parameter.Type != null) {#>
                        ParameterType = typeof(<#=parameter.Type#>),
<#}#>
                        IsRequired = <#=parameter.IsOptional ? "false" : "true"#>,
<#if (parameter.DefaultValue != null) {#>
                        DefaultValue = <#=parameter.DefaultValue#>,
<#}#>
                    },
<#}#>
                },
<#}#>
            };
        }
<#}#>
    }
<#if (!String.IsNullOrEmpty(NameSpace)) {#>
}
<#}#>

<#+
public string NameSpace {get; set;}
public string ClassName {get; set;}
public IEnumerable<SourceGeneratorFunctionContract> FunctionContracts {get; set;}
public bool IsStatic {get; set;} = false;
#>