<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:Locale="urn:Locale-namespace">

	<xsl:include href="Locale.xsl"></xsl:include>

	<xsl:variable name="CustomPressureUnits" select="Locale:PressureUnits()"/>
	<xsl:variable name="PressureConversionFactor" select="Locale:PressureUnitsConversion()" />
	<xsl:variable name="PressureType" select="Locale:PressureUnitsType()" />
	<xsl:variable name="PressurePrecision" select="Locale:PressureUnitsPrecision()" />
	<xsl:variable name="IsEmpowerInstalled" select="Locale:IsEmpower()" />

	<xsl:template match="*">
	
		<xsl:variable name="VarName" select="name()"/>
		<xsl:variable name="TypeNameNode">
			<xsl:value-of select="$TheSchema//xsd:element[@name=$VarName]/@type"/>
		</xsl:variable>
		<xsl:variable name="TypeName" select="string($TypeNameNode)"/>
		<xsl:variable name="IsField" select="string-length($TheSchema//xsd:complexType[@name=$TypeName])=0"/>
		<xsl:variable name="IsList" select="string-length($TheSchema//xsd:complexType[@name=$TypeName])>0"/>
		<xsl:variable name="IsTable" select="string-length($TheSchema//xsd:complexType[@name=$TypeName]/xsd:sequence/xsd:element/xsd:complexType)>0"/>
		<xsl:variable name="IsChildOfRoot" select="parent::node()=/" />
		<xsl:variable name="IsFirstChildOfRoot" select="$IsChildOfRoot=1 and name(.)=name(../*[1])"/>
		<xsl:variable name="HasChildElements" select="count(*) > 0"/>

		<xsl:variable name="NameOfFollowingSibling" select="name(following-sibling::*[1])"/>
		<xsl:variable name="FollowingSiblingTypeNameNode">
			<xsl:value-of select="$TheSchema//xsd:element[@name=$NameOfFollowingSibling]/@type"/>
		</xsl:variable>
		<xsl:variable name="FollowingSiblingTypeName" select="string($FollowingSiblingTypeNameNode)"/>
		<xsl:variable name="FollowingSiblingIsField" select="string-length($TheSchema//xsd:complexType[@name=$FollowingSiblingTypeName])=0"/>
		<xsl:variable name="FollowingSiblingIsTable" select="string-length($TheSchema//xsd:complexType[@name=$FollowingSiblingTypeName]/xsd:sequence/xsd:element/xsd:complexType)>0"/>
		<xsl:variable name="FollowingSiblingChildCount" select="count($TheSchema//xsd:complexType[@name=$FollowingSiblingTypeName]/xsd:sequence/xsd:element)"/>
		<xsl:variable name="FollowingSiblingIsModule" select="$FollowingSiblingIsTable=False and $FollowingSiblingChildCount>0"/>

		<xsl:variable name="NameOfPrecedingSibling" select="name(preceding-sibling::*[1])"/>
		<xsl:variable name="PrecedingSiblingTypeNameNode">
			<xsl:value-of select="$TheSchema//xsd:element[@name=$NameOfPrecedingSibling]/@type"/>
		</xsl:variable>
		<xsl:variable name="PrecedingSiblingTypeName" select="string($PrecedingSiblingTypeNameNode)"/>
		<xsl:variable name="PrecedingSiblingIsField" select="string-length($TheSchema//xsd:complexType[@name=$PrecedingSiblingTypeName])=0"/>
		<xsl:variable name="PrecedingSiblingIsTable" select="string-length($TheSchema//xsd:complexType[@name=$PrecedingSiblingTypeName]/xsd:sequence/xsd:element/xsd:complexType)>0"/>
		<xsl:variable name="PrecedingSiblingChildCount" select="count($TheSchema//xsd:complexType[@name=$PrecedingSiblingTypeName]/xsd:sequence/xsd:element)"/>
		<xsl:variable name="PrecedingSiblingIsModule" select="$PrecedingSiblingIsTable=False and $PrecedingSiblingChildCount>0"/>
		<xsl:variable name="IsLastChildOfRoot" select="$IsChildOfRoot and $IsField and (string-length($NameOfFollowingSibling)=0 or $FollowingSiblingIsField=0)"/>
		<xsl:if test="$HasChildElements=False and ($IsFirstChildOfRoot or ($IsChildOfRoot and ($PrecedingSiblingIsModule or $PrecedingSiblingIsTable)))">
			<xsl:text disable-output-escaping="yes">
				&lt;FieldList&gt;			
			</xsl:text>
			
			<!-- Empower expects a title element, but we leave it blank for the root element group -->
			<xsl:if test="$IsEmpowerInstalled">
				<xsl:element name="Title"></xsl:element>
			</xsl:if>

		</xsl:if>

		<xsl:if test="not ($IsEmpowerInstalled='1' and $VarName='RunTime' )">
			<xsl:call-template name="Emit"/>
		</xsl:if>

		<xsl:if test="$HasChildElements=False and $IsTable=False and ($IsLastChildOfRoot or ($IsChildOfRoot and ($FollowingSiblingIsTable or $FollowingSiblingIsModule)))">
			<xsl:text disable-output-escaping="yes">
				&lt;/FieldList&gt;
			</xsl:text>
		</xsl:if>
	</xsl:template>

	<!--
		*************************************************************************************************************************
		Emit
		Generate output for element or tree of subelements
		*************************************************************************************************************************
	-->
	<xsl:template name="Emit">


		<!-- Get the variable type (String, Float, Int) -->
		<xsl:variable name="VarName" select="name()"/>

		<xsl:variable name="TypeName">
			<xsl:value-of select="$TheSchema//xsd:element[@name=$VarName]/@type"/>
		</xsl:variable>

		<xsl:variable name="IsTable" select="string-length($TheSchema//xsd:complexType[@name=$TypeName]/xsd:sequence/xsd:element/xsd:complexType/xsd:sequence)>0"/>
		<xsl:variable name="IsList" select="string-length($TheSchema//xsd:complexType[@name=$TypeName])>0"/>
		<xsl:choose>
			<xsl:when test="$IsTable=1">
				<xsl:variable name="TableRowName">
					<xsl:value-of select="$TheSchema//xsd:complexType[@name=$TypeName]/xsd:sequence/xsd:element/@name"/>
				</xsl:variable>
				<xsl:call-template name="Emit-Table">
					<xsl:with-param name="InputVar" select="$VarName"/>
					<xsl:with-param name="InputType" select="$TypeName"/>
					<xsl:with-param name="RowName" select="$TableRowName"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="$IsList=1">
				<xsl:call-template name="Emit-FieldList">
					<xsl:with-param name="InputVar" select="$VarName"/>
					<xsl:with-param name="InputType" select="$TypeName"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<xsl:call-template name="Emit-Field">
					<xsl:with-param name="InputVar" select="$VarName"/>
					<xsl:with-param name="InputType" select="$TypeName"/>
				</xsl:call-template>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<!--
		*************************************************************************************************************************
		Emit-FieldList
		Generate the output for a single parameter in the method
		*************************************************************************************************************************
	-->
	<xsl:template name="Emit-FieldList">
		<xsl:param name="InputVar"/>
		<xsl:param name="InputType"/>

		<xsl:element name="FieldList">
			<xsl:element name="Title">
				<xsl:value-of select="$TheSchema//xsd:element[@name=$InputVar]//xsd:has-property[@name='Prompt']/@value"/>
			</xsl:element>
			<xsl:apply-templates/>
		</xsl:element>
	</xsl:template>

	<!--
		*************************************************************************************************************************
		Emit-Table
		Generate the output for a single parameter in the method
		*************************************************************************************************************************
	-->
	<xsl:template name="Emit-Table">
		<xsl:param name="InputVar"/>
		<xsl:param name="InputType"/>
		<xsl:param name="RowName"/>

		<xsl:element name="Table">

			<xsl:element name="Title">
				<xsl:value-of select="$TheSchema//xsd:element[@name=$InputVar]//xsd:has-property[@name='Prompt']/@value"/>
			</xsl:element>
		
			<xsl:element name="Columns">
				<xsl:for-each select="$TheSchema//xsd:complexType[@name=$InputType]//xsd:element[@name=$RowName]//xsd:element">
					<xsl:call-template name="Insert-Column"/>
				</xsl:for-each>
			</xsl:element>
		
			<xsl:element name="Rows">
				<xsl:for-each select="child::*">
					<xsl:element name="Row">
						<xsl:for-each select="*">
							<xsl:element name="Cell">
								<xsl:value-of select="."/>
							</xsl:element>
						</xsl:for-each>
					</xsl:element>
				</xsl:for-each>
			</xsl:element>
		

		</xsl:element>
	</xsl:template>

	<!--
		*************************************************************************************************************************
		Emit-Field
		Generate the output for a single parameter in the method
		*************************************************************************************************************************
	-->
	<xsl:template name="Emit-Field">
		<xsl:param name="InputVar"/>
		<xsl:param name="InputType"/>


		<!-- Convert schema type name e.g. xsd:string to FieldDef name e.g. String -->
		<xsl:variable name="FieldType">
			<xsl:call-template name="Get-Type">
				<xsl:with-param name="InputType" select="$InputType"/>
			</xsl:call-template>
		</xsl:variable>


		<!-- Get the variable name (prompt) for output; default to the element name if no Prompt property is defined -->
		<xsl:variable name="PromptProperty">
			<xsl:value-of  select="$TheSchema//xsd:element[@name=$InputVar]//xsd:has-property[@name='Prompt']/@value"/>
		</xsl:variable>
	
		<xsl:variable name="Prompt">
			<xsl:choose>
				<xsl:when test="string-length($PromptProperty) > 0">
					<xsl:value-of select="$PromptProperty"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="name()"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<!--	
	<xsl:variable name="DisplayAsTable">
		<xsl:value-of select="$TheSchema//xsd:schema/xsd:complexType[@name=$InputType]/xsd:annotation/xsd:appinfo/xsd:has-property[@name='DisplayAsTable']/@value"/>
	</xsl:variable>
-->
		<!--
	<xsl:choose>
		<xsl:when test="$DisplayAsTable='true'">
			<xsl:element name="Table">
				<xsl:element name="Title"><xsl:value-of select="$TheSchema//xsd:schema/xsd:complexType[@name=$InputType]/xsd:annotation/xsd:appinfo/xsd:has-property[@name='Prompt']/@value"/></xsl:element>
				<xsl:element name="Columns">
					<xsl:for-each select="$TheSchema//xsd:schema/xsd:complexType[@name=$InputType]/xsd:sequence/xsd:element/xsd:complexType/xsd:sequence/*">
						<xsl:element name="Column">
							<xsl:attribute name="name"><xsl:value-of select="./xsd:annotation/xsd:appinfo/xsd:has-property[@name='Prompt']/@value"></xsl:value-of></xsl:attribute>
							<xsl:attribute name="units"><xsl:value-of select="./xsd:annotation/xsd:appinfo/xsd:has-property[@name='units']/@value"></xsl:value-of></xsl:attribute>
							<xsl:attribute name="type"><xsl:value-of select="./xsd:annotation/xsd:appinfo/xsd:has-property[@name='type']/@value"></xsl:value-of></xsl:attribute>
							<xsl:attribute name="width"><xsl:value-of select="./xsd:annotation/xsd:appinfo/xsd:has-property[@name='width']/@value"></xsl:value-of></xsl:attribute>
							<xsl:attribute name="precision"><xsl:value-of select="./xsd:annotation/xsd:appinfo/xsd:has-property[@name='precision']/@value"></xsl:value-of></xsl:attribute>
						</xsl:element>
					</xsl:for-each>
				</xsl:element>
				<xsl:element name="Rows">
					<xsl:for-each select="child::node()">
						<xsl:element name="Row">
							<xsl:for-each select="child::node()">
								<xsl:element name="Cell"><xsl:value-of select="."/></xsl:element>
							</xsl:for-each>
						</xsl:element>
					</xsl:for-each>
				</xsl:element>
			</xsl:element>
		</xsl:when>
		<xsl:otherwise>
-->
		<xsl:element name="Field">

			<xsl:attribute name="name">
				<xsl:value-of select="$Prompt"/>
			</xsl:attribute>
				
			<xsl:attribute name="type">
				<xsl:value-of select="$FieldType"/>
			</xsl:attribute>


			<!-- When data type is Float, get the precision -->
			<xsl:if test="$FieldType='Float'">
				<xsl:variable name="Precision" select="$TheSchema//xsd:simpleType[@name=$InputType]/xsd:restriction/xsd:fractionDigits/@value"/>
				<xsl:if test="string-length($Precision) > 0">
					<xsl:attribute name="precision">
						<xsl:value-of select="$Precision"/>
					</xsl:attribute>
				</xsl:if>
			</xsl:if>
	

			<!-- Get the units descriptor and output it only if found -->
			<xsl:variable name="Units" select="$TheSchema//xsd:element[@name=$InputVar]//xsd:has-property[@name='Units']/@value"/>
			<xsl:if test="string-length($Units) > 0">
				<xsl:attribute name="units">
					<xsl:choose>
						<xsl:when test="$Units=$NativePressureUnits">
							<xsl:value-of select="$CustomPressureUnits"/>
						</xsl:when>
						<xsl:otherwise>
							<xsl:value-of select="$Units"/>
						</xsl:otherwise>
					</xsl:choose>
				</xsl:attribute>
			</xsl:if>
				
			<xsl:variable name="TheData" select="."/>
			<xsl:choose>
				<xsl:when test="$Units=$NativePressureUnits">
					<xsl:variable name="NumberFormat">
						<xsl:choose>
							<xsl:when test="$PressureType = 'Int'">
								<xsl:text>0</xsl:text>
							</xsl:when>
							<xsl:otherwise>
								<xsl:choose>
									<xsl:when test="$PressurePrecision = 2">
										<xsl:text>0.00</xsl:text>
									</xsl:when>
									<xsl:when test="$PressurePrecision = 1">
										<xsl:text>0.0</xsl:text>
									</xsl:when>
									<xsl:otherwise>
										<xsl:text>0</xsl:text>
									</xsl:otherwise>
								</xsl:choose>
							</xsl:otherwise>
						</xsl:choose>
					</xsl:variable>
					<xsl:value-of select="format-number( $PressureConversionFactor * $TheData, $NumberFormat )"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="$TheData"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:element>
		<!--
		</xsl:otherwise>
	</xsl:choose>
-->
	</xsl:template>
	<!--
		*************************************************************************************************************************
		Get-Type
		Given a type name from the schema (e.g. xsd:string), this template produces a FieldDef-style type (e.g. String)
		*************************************************************************************************************************
-->
	<xsl:template name="Get-Type">
		<xsl:param name="InputType"/>

		<xsl:variable name="BaseType" select="$TheSchema//xsd:simpleType[@name=$InputType]/xsd:restriction/@base"/>
		<xsl:variable name="ComplexType" select="$TheSchema//xsd:complexType[@name=$InputType]"/>
		<xsl:variable name="UnionMembers" select="$TheSchema//xsd:simpleType[@name=$InputType]/xsd:union/@memberTypes"/>
		<!--
<xsl:text>INPUTTYPE:</xsl:text>
<xsl:value-of select="$InputType"/>
-->
		<xsl:variable name="UnionType">
			<xsl:value-of select="substring-before($UnionMembers,' ')"/>
		</xsl:variable>

		<xsl:choose>

			<xsl:when test="string-length($UnionType)>0">
				<xsl:variable name="BaseUnionType" select="$TheSchema//xsd:simpleType[@name=$UnionType]/xsd:restriction/@base"/>
				<xsl:choose>
					<xsl:when test="$BaseUnionType = 'xsd:string'">
						<xsl:text>String</xsl:text>
					</xsl:when>
					<xsl:otherwise>
						<xsl:text>Unknown (Union)</xsl:text>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:when>


			<!-- PressureLimit is a special case that supports custom units -->
			<xsl:when test="$InputType = 'tPressureLimit'">
				<xsl:value-of select="$PressureType"/>
				<xsl:fallback/>
			</xsl:when>				
			

			<!-- Time and Curve are special cases which unionize a string and a numeric value -->
			<xsl:when test="$InputType = 'tTime'">
				<xsl:call-template name="Get-Type">
					<xsl:with-param name="InputType">tRunTime</xsl:with-param>
				</xsl:call-template>
			</xsl:when>
	
			<xsl:when test="$InputType = 'tCurve'">
				<xsl:call-template name="Get-Type">
					<xsl:with-param name="InputType">tCurveNumber</xsl:with-param>
				</xsl:call-template>
			</xsl:when>
		
			<xsl:when test="$BaseType = 'xsd:string'">
				<xsl:text>String</xsl:text>
			</xsl:when>
			
			<xsl:when test="$BaseType = 'xsd:float'">
				<xsl:text>Float</xsl:text>
			</xsl:when>
			
			<xsl:when test="$BaseType = 'xsd:integer'">
				<xsl:text>Int</xsl:text>
			</xsl:when>
			
			<xsl:when test="$BaseType = 'xsd:int'">
				<xsl:text>Int</xsl:text>
			</xsl:when>
			
			<xsl:when test="$InputType = 'xsd:boolean'">
				<xsl:text>String</xsl:text>
			</xsl:when>

			<xsl:when test="$InputType = 'xsd:string'">
				<xsl:text>String</xsl:text>
			</xsl:when>

			<xsl:when test="$InputType = 'xsd:float'">
				<xsl:text>Float</xsl:text>
			</xsl:when>

			<xsl:when test="string-length($ComplexType) > 0">
				<xsl:value-of select="$InputType"/>
			</xsl:when>

			<xsl:otherwise>
				<xsl:text>Unknown</xsl:text>
			</xsl:otherwise>
			

		</xsl:choose>
		

	</xsl:template>
	<!--
		*************************************************************************************************************************
		Get-Precision
		Given a type name from the schema (e.g. tFlow), this template produces a precision value. This should only
		be called for types that are known to be of type Float. In the absence of a value, '0' is returned.
		*************************************************************************************************************************
-->
	<xsl:template name="Get-Precision">
		<xsl:param name="InputType"/>
		<xsl:variable name="Precision" select="$TheSchema//xsd:simpleType[@name=$InputType]/xsd:restriction/xsd:fractionDigits/@value"/>

		<xsl:choose>

			<xsl:when test="string-length($Precision) > 0">
				<xsl:value-of select="$Precision"/>
			</xsl:when>
			

			<!-- Time and Curve are special cases which unionize a string and a numeric value -->

			<xsl:when test="$InputType = 'tTime'">
				<xsl:call-template name="Get-Precision">
					<xsl:with-param name="InputType">tRunTime</xsl:with-param>
				</xsl:call-template>
			</xsl:when>
	
			<xsl:when test="$InputType = 'tCurve'">
				<xsl:call-template name="Get-Precision">
					<xsl:with-param name="InputType">tCurveNumber</xsl:with-param>
				</xsl:call-template>
			</xsl:when>
			

		</xsl:choose>
		

	</xsl:template>
	<!--
		*************************************************************************************************************************
		Insert-Column
		Adds a column definition to a table
		*************************************************************************************************************************
-->
	<xsl:template name="Insert-Column">
		<!-- Generic column rules -->
		<xsl:element name="Column">
	
			<xsl:attribute name="name">
				<xsl:value-of select=".//xsd:has-property[@name='Prompt']/@value"/>
			</xsl:attribute>
	
			<xsl:variable name="TheUnits">
				<xsl:value-of select=".//xsd:has-property[@name='Units']/@value"/>
			</xsl:variable>

			<xsl:if test="string-length($TheUnits)>0">
				<xsl:attribute name="units">
					<xsl:value-of select="$TheUnits"/>
				</xsl:attribute>
			</xsl:if>
	
			<xsl:variable name="TypeName">
				<xsl:call-template name="Get-Type">
					<xsl:with-param name="InputType" select="@type"/>
				</xsl:call-template>
			</xsl:variable>
			<xsl:attribute name="type">
				<xsl:value-of select="$TypeName"/>
			</xsl:attribute>
			
			<xsl:if test="$TypeName = 'Float'">
				<xsl:attribute name="precision">
					<xsl:call-template name="Get-Precision">
						<xsl:with-param name="InputType" select="@type"/>
					</xsl:call-template>
				</xsl:attribute>
			</xsl:if>
		</xsl:element>
	</xsl:template>
</xsl:stylesheet>