<#--
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      https://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
-->
<#-- Prevent freemarker from escaping stuff -->
<#outputformat "undefined">
<#-- Declare the name and type of variables passed in to the template -->
<#-- @ftlvariable name="languageName" type="java.lang.String" -->
<#-- @ftlvariable name="protocolName" type="java.lang.String" -->
<#-- @ftlvariable name="outputFlavor" type="java.lang.String" -->
<#-- @ftlvariable name="helper" type="org.apache.plc4x.language.cs.CsLanguageTemplateHelper" -->
<#-- @ftlvariable name="tracer" type="org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer" -->
<#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" -->
${helper.fileName(protocolName, languageName, outputFlavor)?replace(".", "/")}/model/${type.name}.cs
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

// Code generated by code-generation. DO NOT EDIT.

using System;
using System.Collections.Generic;
using NLog;
using org.apache.plc4net.api.value;
using org.apache.plc4net.spi.generation;
using org.apache.plc4net.spi.model.values;

<#-- TODO: the code below implies that parserArguments will be null if not present... not pretty  -->
<#if type.parserArguments.isPresent()><#assign parserArguments=type.parserArguments.orElseThrow()></#if>
namespace org.apache.plc4net.drivers.${protocolName?replace("-", "")}.${outputFlavor?replace("-", "")}.model
{

    public class ${type.name}
    {

        private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();

        public static IPlcValue StaticParse(ReadBuffer readBuffer<#if type.parserArguments.isPresent()>, <#list type.parserArguments.orElseThrow() as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)} ${parserArgument.name}<#sep>, </#sep></#list></#if>)
        {
        <#assign defaultCaseOutput=false>
        <#assign dataIoTypeDefinition=type.asDataIoTypeDefinition().orElseThrow()>
        <#list dataIoTypeDefinition.switchField.orElseThrow().cases as case>
            <@compress single_line=true>
                <#if case.discriminatorValueTerms?has_content>
                    if(
                    <#list case.discriminatorValueTerms as discriminatorValueTerm>
                        <#assign discriminatorExpression=dataIoTypeDefinition.switchField.orElseThrow().discriminatorExpressions[discriminatorValueTerm?index].asLiteral().orElseThrow().asVariableLiteral().orElseThrow()>
                        <#assign discriminatorType=helper.getDiscriminatorTypes()[discriminatorExpression.name]>
                        ${helper.toParseExpression(dataIoTypeDefinition.switchField.orElseThrow(), discriminatorType, discriminatorExpression, parserArguments)} ==
                        <#if discriminatorType.isEnumTypeReference()>
                        ${helper.getLanguageTypeNameForTypeReference(discriminatorType)}.${helper.toParseExpression(dataIoTypeDefinition.switchField.orElseThrow(), discriminatorType, discriminatorValueTerm, parserArguments)}
                        <#else>
                        ${helper.toParseExpression(dataIoTypeDefinition.switchField.orElseThrow(), discriminatorType, discriminatorValueTerm, parserArguments)}
                        </#if>
                        <#sep> && </#sep>
                    </#list>
                    )
                <#else>
                    <#assign defaultCaseOutput=true>
                </#if>
            </@compress> { // ${case.name}
            <#assign valueDefined=false>
            <#list case.fields as field>
                <#switch field.typeName>
                    <#case "array">
                        <#assign arrayField = field.asArrayField().orElseThrow()>
                        <#assign elementTypeReference = arrayField.type.elementTypeReference>
                // Array field (${arrayField.name})
                <#-- Only update curPos if the length expression uses it -->
                        <#if arrayField.loopExpression.contains("curPos")>
                curPos = readBuffer.getPos() - startPos;
                        </#if>
                <#-- If this is a count array, we can directly initialize an array with the given size -->
                        <#if field.isCountArrayField()>
                // Count array
                List<IPlcValue> ${arrayField.name};
                {
                    var itemCount = ${helper.toParseExpression(arrayField, helper.intTypeReference, arrayField.loopExpression,parserArguments)};
                    ${arrayField.name} = new List<IPlcValue>();
                    for (var curItem = 0; curItem < itemCount; curItem++) {
                        ${arrayField.name}.Add(new ${helper.getPlcValueTypeForTypeReference(elementTypeReference)}(<#if elementTypeReference.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)})<#else>${elementTypeReference.asNonSimpleTypeReference().orElseThrow().name}IO.StaticParse(readBuffer<#if elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.isPresent()>, <#list elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.orElseThrow() as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(elementTypeReference, parserArgument?index))}) (${helper.toParseExpression(arrayField, elementTypeReference, parserArgument,parserArguments)})<#sep>, </#sep></#list></#if>)</#if>);
                    }
                }
                <#-- In all other cases do we have to work with a list, that is later converted to an array -->
                        <#else>
                <#-- For a length array, we read data till the read position of the buffer reaches a given position -->
                            <#if arrayField.isLengthArrayField()>
                // Length array
                var _${arrayField.name}Length = ${helper.toParseExpression(arrayField, helper.intTypeReference, arrayField.loopExpression,parserArguments)};
                var ${arrayField.name}EndPos = readBuffer.getPos() + _${arrayField.name}Length;
                var value = new List<IPlcValue>();
                while(readBuffer.getPos() < ${arrayField.name}EndPos) {
                    value.Add(
                <#if elementTypeReference.isSimpleTypeReference()>
                        new ${helper.getPlcValueTypeForTypeReference(elementTypeReference)}(${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)})
                <#else>${elementTypeReference.asNonSimpleTypeReference().orElseThrow().name}IO.StaticParse(readBuffer
                    <#if elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.isPresent()>,
                        <#list elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.orElseThrow() as parserArgument>
                                (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(elementTypeReference, parserArgument?index))}) (${helper.toParseExpression(arrayField,elementTypeReference, parserArgument,parserArguments)})
                            <#sep>, </#sep>
                        </#list>
                    </#if>
                        )
                </#if>
                    );
                }
                <#-- A terminated array keeps on reading data as long as the termination expression evaluates to false -->
                            <#elseif arrayField.isTerminatedArrayField()>
                // Terminated array
                var ${arrayField.name} = new List<${helper.getLanguageTypeNameForField(arrayField)}>();
                while(!((boolean) (${helper.toParseExpression(arrayField, helper.boolTypeReference, arrayField.loopExpression,parserArguments)}))) {
                    ${arrayField.name}.Add(<#if elementTypeReference.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)}<#else>${elementTypeReference.asNonSimpleTypeReference().orElseThrow().name}IO.StaticParse(readBuffer<#if elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.isPresent()>, <#list elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.orElseThrow() as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(elementTypeReference, parserArgument?index))}) (${helper.toParseExpression(arrayField, elementTypeReference, parserArgument, parserArguments)})<#sep>, </#sep></#list></#if>)</#if>);

                <#-- After parsing, update the current position, but only if it's needed -->
                                <#if arrayField.loopExpression.contains("curPos")>
                    curPos = readBuffer.getPos() - startPos;
                                </#if>
                }
                            </#if>
                        </#if>
                        <#if arrayField.name == "value">
                            <#assign valueDefined=true>
                        </#if>
                    <#break>
                    <#case "const">
                        <#assign constField=field.asConstField().orElseThrow()>

                // Const Field (${constField.name})
                var ${constField.name} = ${helper.getReadBufferReadMethodCall(constField.type.asSimpleTypeReference().orElseThrow(), "", constField)};
                if(${constField.name} != ${dataIoTypeDefinition.name}.${constField.name?upper_case}) {
                    throw new ParseException("Expected constant value " + ${dataIoTypeDefinition.name}.${constField.name?upper_case} + " but got " + ${constField.name});
                }
                        <#if constField.name == "value">
                            <#assign valueDefined=true>
                        </#if>
                    <#break>
                    <#case "enum">
                        <#assign enumField=field.asEnumField().orElseThrow()>

                // Enum field (${enumField.name})
                var ${enumField.name} = ${helper.getLanguageTypeNameForField(enumField)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(enumField.type.asSimpleTypeReference().orElseThrow()), "", enumField)});
                        <#if enumField.name == "value">
                            <#assign valueDefined=true>
                        </#if>
                    <#break>
                    <#case "manual">
                        <#assign manualField=field.asManualField().orElseThrow()>

                // Manual Field (${manualField.name})
                var ${manualField.name} = (${helper.getLanguageTypeNameForField(manualField)}) (${helper.toParseExpression(manualField, manualField.type, manualField.parseExpression,parserArguments)});
                        <#if manualField.name == "value">
                            <#assign valueDefined=true>
                        </#if>
                    <#break>
                    <#case "reserved">
                        <#assign reservedField=field.asReservedField().orElseThrow()>

                // Reserved Field (Compartmentalized so the "reserved" variable can't leak)
                {
                    var reserved = ${helper.getReadBufferReadMethodCall(reservedField.type.asSimpleTypeReference().orElseThrow(), "", reservedField)};
                    if(reserved != ${helper.getReservedValue(reservedField)}) {
                        Logger.Info("Expected constant value {expected} but got {got} for reserved field.", ${reservedField.referenceValue}, reserved);
                    }
                }
                    <#break>
                    <#case "simple">
                        <#assign simpleField=field.asSimpleField().orElseThrow()>

                        <#if helper.isEnumField(simpleField)>
                // Enum field (${simpleField.name})
                var ${simpleField.name} = ${helper.getLanguageTypeNameForField(simpleField)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(simpleField.type), "", simpleField)});
                        <#else>
                // Simple Field (${simpleField.name})
                var ${simpleField.name} = <#if simpleField.type.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(simpleField.type.asSimpleTypeReference().orElseThrow(), "", simpleField)}<#else>${simpleField.type.asNonSimpleTypeReference().orElseThrow().name}IO.StaticParse(readBuffer<#if simpleField.type.asNonSimpleTypeReference().orElseThrow().params.isPresent()>, <#list simpleField.type.asNonSimpleTypeReference().orElseThrow().params.orElseThrow() as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(simpleField.type, parserArgument?index))}) (${helper.toParseExpression(simpleField, simpleField.type, parserArgument,parserArguments)})<#sep>, </#sep></#list></#if>)</#if>;
                        </#if>
                        <#if case.name == "Struct" ||
                            ((case.name == "DATE_AND_TIME") && ((simpleField.name == "year") || (simpleField.name == "month") || (simpleField.name == "day") || (simpleField.name == "hour") || (simpleField.name == "minutes") || (simpleField.name == "seconds"))) ||
                            ((case.name == "DATE_AND_TIME") && (simpleField.name == "secondsSinceEpoch")) ||
                            ((case.name == "DATE") && ((simpleField.name == "year") || (simpleField.name == "month") || (simpleField.name == "day"))) ||
                            ((case.name == "TIME_OF_DAY") && ((simpleField.name == "hour") || (simpleField.name == "minutes") || (simpleField.name == "seconds"))) ||
                        simpleField.name == "value">
                            <#assign valueDefined=true>
                        </#if>
                    <#break>
                </#switch>
            </#list>
            <#if case.name == "Struct">

                <#-- In this case we need to wrap each field in a IPlcValue that matches it's natural type -->
                var _map = new Dictionary<string, IPlcValue>();
                <#list case.fields as field>
                    <#if field.isArrayField()>
                        <#assign field=field.asArrayField().orElseThrow()>
                _map["${field.name}"] = new PlcList(${field.name});
                    <#elseif field.isPropertyField()>
                        <#assign field=field.asPropertyField().orElseThrow()>
                        <#switch helper.getLanguageTypeNameForTypeReference(field.type)>
                            <#case "Boolean">
                _map["${field.name}"] = new PlcBOOL(${field.name});
                                <#break>
                            <#case "Byte">
                _map["${field.name}"] = new PlcSINT(${field.name});
                                <#break>
                            <#case "Short">
                _map["${field.name}"] = new PlcINT(${field.name});
                                <#break>
                            <#case "Integer">
                _map["${field.name}"] = new PlcDINT(${field.name});
                                <#break>
                            <#case "Long">
                _map["${field.name}"] = new PlcLINT(${field.name});
                                <#break>
                            <#case "BigInteger">
                _map["${field.name}"] = new PlcBigInteger(${field.name});
                                <#break>
                            <#case "Float">
                _map["${field.name}"] = new PlcREAL(${field.name});
                                <#break>
                            <#case "Double">
                _map["${field.name}"] = new PlcLREAL(${field.name});
                                <#break>
                            <#case "BigDecimal">
                _map["${field.name}"] = new PlcBigDecimal(${field.name});
                                <#break>
                            <#case "String">
                _map["${field.name}"] = new PlcSTRING(${field.name});
                                <#break>
                            <#case "LocalTime">
                _map["${field.name}"] = new PlcTIME_OF_DAY(${field.name});
                                <#break>
                            <#case "LocalDate">
                _map["${field.name}"] = new PlcDATE(${field.name});
                                <#break>
                            <#case "LocalDateTime">
                _map["${field.name}"] = new PlcDATE_AND_TIME(${field.name});
                                <#break>
                        </#switch>
                    </#if>
                </#list>
                <#assign valueDefined=true>
            </#if>

            <#if valueDefined>
                <#switch case.name>
                    <#case "TIME">
                return new PlcTIME(TimeSpan.FromSeconds(value));
                    <#break>
                    <#case "LTIME">
                return new PlcTIME(TimeSpan.FromMilliseconds(value));
                    <#break>
                    <#case "TIME_OF_DAY">
                return new PlcTIME_OF_DAY(DateTime.Now); <#-- TODO: Convert uint to time-of-day ... -->
                    <#break>
                    <#case "DATE">
                    <#if helper.hasFieldsWithNames(case.fields, "value")>
                return new PlcDATE(DateTime.Now); <#-- TODO: Convert ushort to date ... -->
                    <#elseif helper.hasFieldsWithNames(case.fields, "year", "month", "day")>
                return new PlcDATE(LocalDate.of(year.intValue(), (month == 0) ? 1 : month.intValue(), (day == 0) ? 1 : day.intValue());
                    </#if>
                    <#break>
                    <#case "TIME_OF_DAY">
                    <#if helper.hasFieldsWithNames(case.fields, "hour", "minutes", "seconds", "nanos")>
                LocalTime value = LocalTime.of(hour.intValue(), minutes.intValue(), seconds.intValue(), (int) (nanos / 1000000));
                    <#elseif helper.hasFieldsWithNames(case.fields, "hour", "minutes", "seconds")>
                LocalTime value = LocalTime.of(hour.intValue(), minutes.intValue(), seconds.intValue());
                    </#if>
                return new PlcTIME_OF_DAY(value);
                    <#break>
                    <#case "DATE_AND_TIME">
                    <#if helper.hasFieldsWithNames(case.fields, "year", "month", "day", "hour", "minutes", "seconds", "nanos")>
                var value = new DateTime(year, (month == 0) ? 1 : month, (day == 0) ? 1 : day, hour, minutes, seconds, (int) (nanos / 1000000));
                    <#elseif helper.hasFieldsWithNames(case.fields, "year", "month", "day", "hour", "minutes", "seconds")>
                var value = new DateTime(year, (month == 0) ? 1 : month, (day == 0) ? 1 : day, hour, minutes, seconds, 0);
                    <#elseif helper.hasFieldsWithNames(case.fields, "secondsSinceEpoch")>
                var value = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(value);
                    </#if>
                return new PlcDATE_AND_TIME(value);
                    <#break>
                    <#case "CHAR">
                return new PlcCHAR(Convert.ToChar(value));
                    <#break>
                    <#case "WCHAR">
                return new PlcWCHAR(Convert.ToChar(value));
                    <#break>
                    <#case "Struct">
                return new PlcStruct(_map);
                    <#break>
                    <#case "List">
                return new PlcList(value);
                    <#break>
                    <#default>
                return new Plc${case.name}(value);
                </#switch>
            </#if>
            }<#sep> else </#sep></#list>
        <#if !defaultCaseOutput>
            return null;
        </#if>
        }

<#if outputFlavor != "passive">
            public static WriteBuffer StaticSerialize(IPlcValue _value<#if type.parserArguments.isPresent()>, <#list type.parserArguments.orElseThrow() as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)} ${parserArgument.name}<#sep>, </#sep></#list></#if>)
            {
                return StaticSerialize(_value<#if type.parserArguments.isPresent()>, <#list type.parserArguments.orElseThrow() as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if>, ByteOrder.BIG_ENDIAN);
            }

            public static WriteBuffer StaticSerialize(IPlcValue _value<#if type.parserArguments.isPresent()>, <#list type.parserArguments.orElseThrow() as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)} ${parserArgument.name}<#sep>, </#sep></#list></#if>, ByteOrder byteOrder)
            {
        <#assign defaultCaseOutput=false>
        <#assign dataIoTypeDefinition=type.asDataIoTypeDefinition().orElseThrow()>
        <#list dataIoTypeDefinition.switchField.orElseThrow().cases as case>
        <@compress single_line=true>
            <#if case.discriminatorValueTerms?has_content>
                    if(
                <#list case.discriminatorValueTerms as discriminatorValueTerm>
                    <#assign discriminatorExpression=dataIoTypeDefinition.switchField.orElseThrow().discriminatorExpressions[discriminatorValueTerm?index].asLiteral().orElseThrow().asVariableLiteral().orElseThrow()>
                    <#assign discriminatorType=helper.getDiscriminatorTypes()[discriminatorExpression.name]>
                            ${helper.toParseExpression(dataIoTypeDefinition.switchField.orElseThrow(), discriminatorType, discriminatorExpression, parserArguments)} ==
                    <#if discriminatorType.isEnumTypeReference()>
                            ${helper.getLanguageTypeNameForTypeReference(discriminatorType)}.${helper.toParseExpression(dataIoTypeDefinition.switchField.orElseThrow(), discriminatorType, discriminatorValueTerm, parserArguments)}
                    <#else>
                            ${helper.toParseExpression(dataIoTypeDefinition.switchField.orElseThrow(), discriminatorType, discriminatorValueTerm, parserArguments)}
                    </#if>
                    <#sep> && </#sep>
                </#list>
                )
            <#else>
                <#assign defaultCaseOutput=true>
            </#if>
        </@compress> { // ${case.name}
                var writeBuffer = new WriteBuffer();

            <#list case.fields as field>
                <#switch field.typeName>
                    <#case "array">
                        <#assign arrayField=field.asArrayField().orElseThrow()>
                        <#assign elementTypeReference = arrayField.type.elementTypeReference>
                PlcList values = (PlcList) _value;

                        <#if case.name == "Struct">
                foreach (IPlcValue val in values.GetStruct()["${arrayField.name}"].GetList()) {
                    ${helper.getLanguageTypeNameForTypeReference(elementTypeReference)} value = (${helper.getLanguageTypeNameForTypeReference(elementTypeReference)}) val.Get${helper.getLanguageTypeNameForTypeReference(elementTypeReference)?cap_first}();
                    ${helper.getWriteBufferWriteMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "value", arrayField)};
                }
                        <#else>
                foreach (IPlcValue val in values.GetList()) {
                    ${helper.getLanguageTypeNameForTypeReference(elementTypeReference)} value = val.Get${helper.getLanguageTypeNameForTypeReference(elementTypeReference)?cap_first}();
                    ${helper.getWriteBufferWriteMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "(" + arrayField.name + ")", arrayField)};
                }
                        </#if>

                    <#if case.name == "BOOL">
                while (writeBuffer.getPos() < writeBuffer.getData().length) {
                    writeBuffer.writeBit(false);
                }
                    </#if>
                    <#break>
                    <#case "const">
                        <#assign constField=field.asConstField().orElseThrow()>
                // Const Field (${constField.name})
                ${helper.getWriteBufferWriteMethodCall(constField.type.asSimpleTypeReference().orElseThrow(), constField.referenceValue, constField)};
                    <#break>
                    <#case "enum">
                        <#assign enumField=field.asEnumField().orElseThrow()>
                // Enum field (${enumField.name})
                var ${enumField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${enumField.name?cap_first}();
                ${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(field.asTypedField().orElseThrow().type), "(" + enumField.name + ".getValue())", enumField)};
                    <#break>
                    <#case "manual">
                        <#assign manualField=field.asManualField().orElseThrow()>
                // Manual Field (${manualField.name})
                ${helper.toSerializationExpression(manualField, manualField.type, manualField.serializeExpression, type.parserArguments.orElse(null))};
                    <#break>
                    <#case "reserved">
                        <#assign reservedField=field.asReservedField().orElseThrow()>
                // Reserved Field
                ${helper.getWriteBufferWriteMethodCall(reservedField.type.asSimpleTypeReference().orElseThrow(), helper.getReservedValue(reservedField), reservedField)};
                    <#break>
                    <#case "simple">
                        <#assign simpleField=field.asSimpleField().orElseThrow()>
                // Simple Field (${simpleField.name})
                        <#if case.name == "Struct">
                var ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.GetStruct()["${simpleField.name}"].Get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
                        <#else>
                            <#if simpleField.name == "value">
                var ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.Get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
                            <#else>
                                <#-- Just for now -->
                var ${simpleField.name} = ${helper.getNullValueForTypeReference(simpleField.type)};
                            </#if>
                        </#if>
                        <#if simpleField.type.isSimpleTypeReference()>
                ${helper.getWriteBufferWriteMethodCall(simpleField.type.asSimpleTypeReference().orElseThrow(), "(" + simpleField.name + ")", simpleField)};
                        <#else>
                ${simpleField.type.asNonSimpleTypeReference().orElseThrow().name}IO.StaticSerialize(writeBuffer, ${simpleField.name});
                        </#if>
                    <#break>
                </#switch>
            </#list>
            return writeBuffer;
        }<#sep> else </#sep></#list>
        <#if !defaultCaseOutput>
        return null;
        </#if>
        }
    }
</#if>

}
</#outputformat>
