<#@ Template Language="VB" HostSpecific="True" Inherits="DynamicTransform" #>
<#@ Output extension="aspx" #>
<#@ assembly name="System.ComponentModel.DataAnnotations" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data.Entity" #>
<#@ assembly name="System.Data.Linq" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.ComponentModel.DataAnnotations" #>
<#@ import namespace="System.Data.Linq.Mapping" #>
<#@ import namespace="System.Data.Objects.DataClasses" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="EnvDTE" #>
<#
Dim viewDataType = CType(Model.ViewDataType, CodeType)
Dim mvcViewDataTypeGenericString As String = If(viewDataType IsNot Nothing, "(Of " & viewDataType.FullName & ")", String.Empty)
Dim CPHCounter As Integer = 1
#>
<#
If Model.IsContentPage Then
#>
<%@ Page Title="" Language="VB" MasterPageFile="~<#= Model.Layout #>" Inherits="System.Web.Mvc.ViewPage<#= mvcViewDataTypeGenericString #>" %>

<#
	For Each cphid As String In Model.SectionNames 
        If cphid.Equals("TitleContent", StringComparison.OrdinalIgnoreCase) Then
#>
<asp:Content ID="Content<#= CPHCounter #>" ContentPlaceHolderID="<#= cphid #>" runat="server">
    <#= Model.ViewName #>
</asp:Content>

<#
                CPHCounter += 1
        End If
    Next
#>
<asp:Content ID="Content<#= CPHCounter #>" ContentPlaceHolderID="<#= Model.PrimarySectionName #>" runat="server">

<h2><#= Model.ViewName #></h2>

<#
Else
#>
<%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage<#= mvcViewDataTypeGenericString #>" %>
<!DOCTYPE html>

<html>
<head runat="server">
    <title><#= Model.ViewName #></title>
</head>
<body>
<#
    PushIndent("    ")
End If
#>
<fieldset>
    <legend><#= If(Model.ViewDataTypeName, String.Empty) #></legend>
<#
For Each modelProp As ModelProperty In GetModelProperties(Model.ViewDataType, True)
    If (Not modelProp.IsPrimaryKey AndAlso Not modelProp.IsForeignKey) Then
#>

    <div class="display-label"><#= modelProp.Name #></div>
    <div class="display-field"><%: <#= modelProp.ValueExpression #> %></div>
<#
    End If
Next
#>
</fieldset>
<p>
<# If Not String.IsNullOrEmpty(Model.PrimaryKeyName) Then #>
    <%: Html.ActionLink("Edit", "Edit", New With {.id = Model.<#= Model.PrimaryKeyName #>}) %> |
    <%: Html.ActionLink("Back to List", "Index") %>
<#
Else
#>
    <%--<%: Html.ActionLink("Edit", "Edit", New With {.id = Model.PrimaryKey}) %> |--%>
    <%: Html.ActionLink("Back to List", "Index") %>
<#
End If
#>
</p>
<#
' The following code closes the asp:Content tag used in the case of a master page and the body and html tags in the case of a regular view page
#>
<#
If Model.IsContentPage
#>

</asp:Content>
<#
	For Each cphid As String In Model.SectionNames 
        If String.Compare(cphid, "TitleContent", StringComparison.OrdinalIgnoreCase) <> 0 AndAlso String.Compare(cphid, Model.PrimarySectionName, StringComparison.OrdinalIgnoreCase) <> 0 Then
            CPHCounter +=1
#>

<asp:Content ID="Content<#= CPHCounter #>" ContentPlaceHolderID="<#= cphid #>" runat="server">
</asp:Content>
<#
        End If
    Next
#>
<#
Else If Not Model.IsContentPage Then
    ClearIndent()
#>
</body>
</html>
<#
End If
#>

<#+
' Describes the information about a property on the model
Private Class ModelProperty
    Public Name As String
    Public ValueExpression As String
    Public Type As CodeTypeRef
    Public IsReadOnly As Boolean
    Public IsPrimaryKey As Boolean
	Public IsForeignKey As Boolean
End Class

' Change this list to include any non-primitive types you think should be eligible to be edited using a textbox
Private Shared bindableNonPrimitiveTypes As Type() = New Type() {
    GetType(String),
    GetType(Decimal),
    GetType(Guid),
    GetType(DateTime),
    GetType(DateTimeOffset),
    GetType(TimeSpan)
}

' Call this to get the list of properties in the model. Change this to modify or add your
' own default formatting for display values.
Private Function GetModelProperties(ByVal type As CodeType, ByVal includeUnbindableProperties As Boolean) As List(Of ModelProperty)
    Dim results As List(Of ModelProperty) = GetEligibleProperties(type, includeUnbindableProperties)
    
    For Each modelProp As ModelProperty In results
        If ((modelProp.Type.UnderlyingTypeIs(GetType(Double))) OrElse (modelProp.Type.UnderlyingTypeIs(GetType(Decimal)))) Then
            modelProp.ValueExpression = ("String.Format(""{0:F}"", " & modelProp.ValueExpression & ")")
        ElseIf (modelProp.Type.UnderlyingTypeIs(GetType(DateTime))) Then
            modelProp.ValueExpression = ("String.Format(""{0:g}"", " & modelProp.ValueExpression & ")")
		ElseIf (Not IsBindableType(modelProp.Type))
			modelProp.ValueExpression = GetValueExpression("Model." & modelProp.Name, CType(modelProp.Type.CodeType, CodeType))
        End If
    Next

    Return results
End Function

' Change this list to include the names of properties that should be selected to represent an entity as a single string
Private Shared displayPropertyNames As String() = New String() { "Name", "Title", "LastName", "Surname", "Subject", "Count" }

Private Function GetValueExpression(ByVal propertyExpression As String, ByVal propertyType As CodeType) As String
	If propertyType IsNot Nothing Then
		Dim chosenSubproperty = If(propertyType.DisplayColumnProperty(), propertyType.FindProperty(displayPropertyNames))
		If chosenSubproperty IsNot Nothing Then 
			Dim toStringSuffix = If(chosenSubproperty.Type.AsFullName = "System.String", "", ".ToString()")
			Return String.Format("(If({0} Is Nothing, ""None"", {0}.{1}{2}))", propertyExpression, chosenSubproperty.Name, toStringSuffix)
		End If
	End If
	Return "Html.DisplayTextFor(Function(model) " & propertyExpression & ").ToString()"
End Function

' Helper
Private Function GetEligibleProperties(ByVal type As CodeType, ByVal includeUnbindableProperties As Boolean) As List(Of ModelProperty)
    Dim results As New List(Of ModelProperty)

	If type IsNot Nothing Then
		For Each prop As CodeProperty In type.VisibleMembers().OfType(Of CodeProperty)()
			Dim propValue = prop
			If (prop.IsReadable() AndAlso (Not prop.HasIndexParameters()) AndAlso (includeUnbindableProperties OrElse IsBindableType(prop.Type))) Then
				results.Add(New ModelProperty() With { _
					.Name = prop.Name, _
					.ValueExpression = ("Model." & prop.Name), _
					.Type = prop.Type, _
					.IsPrimaryKey = Model.PrimaryKeyName = prop.Name, _
					.IsReadOnly = Not prop.IsWriteable(), _
					.IsForeignKey = ParentRelations.Any(Function(x) propValue.Name = x.RelationProperty.Name) _
				})
			End If
		Next
	End If

    Return results
End Function

Private ReadOnly Property ParentRelations As IEnumerable(Of RelatedEntityInfo)
	Get
		Return CType(Model.RelatedEntities, IEnumerable).OfType(Of RelatedEntityInfo)().Where(Function(x) x.RelationType = RelationType.Parent)
	End Get
End Property

' Helper
Private Function IsBindableType(ByVal type As CodeTypeRef) As Boolean
    Return type.UnderlyingIsPrimitive() OrElse bindableNonPrimitiveTypes.Any(Function(x) type.UnderlyingTypeIs(x))
End Function
#>