<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns:msxsl="urn:schemas-microsoft-com:xslt"
	xmlns:exsl="urn:schemas-microsoft-com:xslt"
	xmlns:picnet="http://www.picnet.com.au">

	<xsl:template name="default-null-value">
		<xsl:param name="objecttype"/>
		<xsl:choose>
			<xsl:when test="$objecttype = 'int' or $objecttype = 'decimal' or $objecttype = 'double'">0</xsl:when>
			<xsl:when test="$objecttype = 'bool'">false</xsl:when>
			<xsl:when test="$objecttype = 'DateTime'">System.Data.SqlTypes.SqlDateTime.MinValue.Value</xsl:when>			
			<xsl:otherwise>null</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template name="is-root-entity">
		<xsl:param name="entity"/>
		<xsl:value-of select="count($entity/field[picnet:GetTypeSafe(@type) != picnet:GetObjectType(picnet:GetTypeSafe(@type), @objecttype)]) = 0"/>
	</xsl:template>
	
	<xsl:template name="actual-type">
		<xsl:param name="field"/>
		<xsl:choose>
			<xsl:when test="$field/encrypted='true'">string</xsl:when>
			<xsl:otherwise><xsl:value-of select="picnet:GetObjectType(picnet:GetTypeSafe($field/@type), $field/@objecttype)"/></xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template name="propertyname">
		<xsl:param name="field"/>
		
		<xsl:choose>
			<xsl:when test="not($field/@fieldname) or $field/@fieldname = ''"><xsl:value-of select="$field/@name"/></xsl:when>
			<xsl:otherwise><xsl:value-of select="$field/@fieldname"/>ID</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template name="fieldname">
		<xsl:param name="field"/>
		<xsl:param name="lowercase"/>
		
		<xsl:variable name="name">
			<xsl:choose>
				<xsl:when test="not($field/@fieldname) or $field/@fieldname = ''"><xsl:value-of select="$field/@name"/></xsl:when>
				<xsl:otherwise><xsl:value-of select="$field/@fieldname"/></xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:choose>
			<xsl:when test="picnet:GetTypeSafe($field/@type) != picnet:GetObjectType(picnet:GetTypeSafe($field/@type), $field/@objecttype)">
				<xsl:value-of select="picnet:FieldName($field/@fieldname, $field/@name,  $lowercase)"/>
			</xsl:when>
			<xsl:when test="$lowercase">
				<xsl:value-of select="picnet:ToLower($name)"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$name"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>	
		
	<!-- Can only be called within a correct (filtered for entities) 'field' context -->
	<xsl:template match="field" mode="entities-list-name">
		<xsl:variable name="thistype" select="picnet:GetObjectType(picnet:GetTypeSafe(@type), @objecttype)"/>
		<xsl:variable name="method-name-prefix">
			<xsl:choose>
				<xsl:when test="count(../field[picnet:GetObjectType(picnet:GetTypeSafe(@type), @objecttype)=$thistype]) > 1">
					<xsl:value-of select="concat(picnet:FieldName(../@fieldname, ../@name, false()), '_', picnet:FieldName(@fieldname, @name, false()))"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="picnet:FieldName(../@fieldname, ../@name, false())"/>
				</xsl:otherwise>
			</xsl:choose>		
		</xsl:variable>
		<xsl:value-of select="$method-name-prefix"/>
	</xsl:template>
			
	<msxsl:script implements-prefix="picnet" language="C#">
<![CDATA[		
	public static string GetTypeSafe(string type) 
	{		
		return String.IsNullOrEmpty(type) ? "int" : type;		
	}
	
	public static string GetObjectType(string type, string objecttype) 
	{
		if (!String.IsNullOrEmpty(objecttype)) { return objecttype; }
		return GetTypeSafe(type);
	}
	
	public static bool IsRelationField(string name) 
	{
		return name.EndsWith("ID");
	}
	
	public static string StringValueOrNull(string value) 
	{
		return value == null ? "null" : "\"" + value + "\"";
	}
	
	public static string FieldName(string fieldname, string columnname, bool lowercase) 
	{
		string name = fieldname == null || fieldname.Length == 0 ? columnname : fieldname;
		return (lowercase ? name.Replace("ID", "").ToLower() : name.Replace("ID", ""));
	}
	
	public static string ToLower(string str) 
	{
		return str.ToLower();
	}
	
	public static bool EndsWith(string str, string suffix) 
	{
		return str.EndsWith(suffix);
	}

	public int Length(string str) { return str == null ? 0 : str.Length; }
		
	public void WriteText(string filename, object text)
	{
		if(System.IO.File.Exists(filename)) { System.IO.File.Delete(filename); }
		using (System.IO.FileStream s = System.IO.File.OpenWrite(filename))
		{
			System.IO.StreamWriter sw = new System.IO.StreamWriter(s);
			sw.Write(text);
			sw.Flush();
			sw.Close();
			s.Close();	
		}					
	}
		
    public void WriteXML(string filename, XPathNodeIterator nodes)
    {
    	if(System.IO.File.Exists(filename)) { System.IO.File.Delete(filename); }
    	if (nodes.Count == 0) throw new ApplicationException("nodes are empty.");    	
	  	XmlTextWriter tw = new XmlTextWriter(filename, UTF8Encoding.UTF8);
	  	tw.Formatting = Formatting.Indented;
		SerializeNode(tw, nodes.Current);
		tw.Flush();
		tw.Close();				
	}
	
	public void CleanXML(string filename) {
		System.IO.TextReader r = System.IO.File.OpenText(filename);
		string text = r.ReadToEnd();
		r.Close();
		text = text.Replace(" xmlns=\"\"", "");		
		
		WriteText(filename, text);		
	}

	public static void SerializeNode(XmlWriter w, XPathNavigator nav)
	{
		switch (nav.NodeType)
		{
			case XPathNodeType.Element:
				w.WriteStartElement(nav.Prefix, nav.LocalName, nav.NamespaceURI);
				if (nav.MoveToFirstAttribute())
				{
					w.WriteStartAttribute(nav.Prefix, nav.LocalName, nav.NamespaceURI);
					w.WriteString(nav.Value);
					w.WriteEndAttribute();

					while (nav.MoveToNextAttribute())
					{
						w.WriteStartAttribute(nav.Prefix, nav.LocalName, nav.NamespaceURI);
						w.WriteString(nav.Value);
						w.WriteEndAttribute();
					}
					nav.MoveToParent();
				}
				if (nav.HasChildren)
				{
					bool more = nav.MoveToFirstChild();
					while (more)
					{
						SerializeNode(w, nav);
						more = nav.MoveToNext();
					}
					nav.MoveToParent();
				}
				w.WriteEndElement();
				break;
			case XPathNodeType.Text:
				w.WriteString(nav.Value);
				break;
			case XPathNodeType.ProcessingInstruction:
				w.WriteProcessingInstruction(nav.Name, nav.Value);
				break;
			case XPathNodeType.Comment:
				w.WriteComment(nav.Value);
				break;
			case XPathNodeType.Whitespace:
				break;
			case XPathNodeType.SignificantWhitespace:
				break;
		}			
	}				
]]>    
 </msxsl:script>

</xsl:stylesheet>