<#@ template language="C#" HostSpecific="True"  inherits="DynamicTransform" #>
<#@ assembly name="System.Data.Entity" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="EnvDTE" #>
<#@ Output Extension="vb" #>
Imports System.Data.Entity
Imports System.Linq.Expressions
<# foreach(var ns in new[] { Model.ModelTypeNamespace, Model.DbContextNamespace }.Where(x => !string.IsNullOrEmpty(x) && (x != Model.RepositoryNamespace)).Distinct()) { #>
Imports <#= ns #>
<# } #>

<#= T4Scaffolding.Namespaces.BeginVb(Model.RepositoryNamespace, Model.DefaultNamespace) #>
<# 
    var modelType = (CodeType)Model.ModelType; 
    var modelName = modelType.Name; 
    var modelNamePlural = Model.ModelTypePluralized; 
    var contextName = ((CodeType)Model.DbContextType).Name; 
    var primaryKeyProperty = modelType.VisibleMembers().OfType<CodeProperty>().Single(x => x.Name == Model.PrimaryKey);
    var isObjectContext = ((CodeType)Model.DbContextType).IsAssignableTo<System.Data.Objects.ObjectContext>();
#>
    Public Class <#= modelName #>Repository : Implements I<#= modelName #>Repository
        Private context As <#= contextName #> = New <#= contextName #>()

        Public ReadOnly Property All As IQueryable(Of <#= modelName #>) Implements I<#= modelName #>Repository.All
            Get
                Return context.<#= modelNamePlural #>
            End Get
        End Property

        Public Function AllIncluding(ByVal ParamArray includeProperties() As Expression(Of Func(Of <#= modelName #>, Object))) As IQueryable(Of <#= modelName #>) Implements I<#= modelName #>Repository.AllIncluding
            Dim query As IQueryable(Of <#= modelName #>) = context.<#= modelNamePlural #>
            For Each includeProperty In includeProperties
                query = query.Include(includeProperty)
            Next
            Return query
        End Function

        Public Function Find(id As <#= primaryKeyProperty.Type.AsString #>) As <#= modelName #> Implements I<#= modelName #>Repository.Find
<# if(isObjectContext) { #>
            Return context.<#= modelNamePlural #>.Single(Function(x) x.<#= Model.PrimaryKey #> = id)
<# } else { #>
            Return context.<#= modelNamePlural #>.Find(id)
<# } #>
        End Function

        Public Sub InsertOrUpdate(<#= modelName.ToLower() #> As <#= modelName #>) Implements I<#= modelName #>Repository.InsertOrUpdate
            If <#= modelName.ToLower() #>.<#= Model.PrimaryKey #> = Nothing Then
                ' New entity
<# if(primaryKeyProperty.Type.AsString == "System.Guid") { #>
                <#= modelName.ToLower() #>.<#= primaryKeyProperty.Name #> = Guid.NewGuid()
<# } #>
<# if(isObjectContext) { #>
                context.<#= modelNamePlural #>.AddObject(<#= modelName.ToLower() #>)
<# } else { #>
                context.<#= modelNamePlural #>.Add(<#= modelName.ToLower() #>)
<# } #>
            Else
                ' Existing entity
<# if(isObjectContext) { #>
                context.<#= modelNamePlural #>.Attach(<#= modelName.ToLower() #>)
                context.ObjectStateManager.ChangeObjectState(<#= modelName.ToLower() #>, EntityState.Modified)
<# } else { #>
                context.Entry(<#= modelName.ToLower() #>).State = EntityState.Modified
<# } #>
            End If
        End Sub

        Public Sub Delete(id As <#= primaryKeyProperty.Type.AsString #>) Implements I<#= modelName #>Repository.Delete
<# if(isObjectContext) { #>
            Dim <#= modelName.ToLower() #> = context.<#= modelNamePlural #>.Single(Function(x) x.<#= Model.PrimaryKey #> = id)
            context.<#= modelNamePlural #>.DeleteObject(<#= modelName.ToLower() #>)
<# } else { #>
            Dim <#= modelName.ToLower() #> = context.<#= modelNamePlural #>.Find(id)
            context.<#= modelNamePlural #>.Remove(<#= modelName.ToLower() #>)
<# } #>
        End Sub

        Public Sub Save() Implements I<#= modelName #>Repository.Save
            context.SaveChanges()
        End Sub

        Public Sub Dispose() Implements IDisposable.Dispose
            context.Dispose()
        End Sub
    End Class

    Public Interface I<#= modelName #>Repository : Inherits IDisposable
        ReadOnly Property All As IQueryable(Of <#= modelName #>)
        Function AllIncluding(ByVal ParamArray includeProperties() As Expression(Of Func(Of <#= modelName #>, Object))) As IQueryable(Of <#= modelName #>)
        Function Find(id As <#= primaryKeyProperty.Type.AsString #>) As <#= modelName #>
        Sub InsertOrUpdate(<#= modelName.ToLower() #> As <#= modelName #>)
        Sub Delete(id As <#= primaryKeyProperty.Type.AsString #>)
        Sub Save()
    End Interface
<#= T4Scaffolding.Namespaces.EndVb(Model.RepositoryNamespace, Model.DefaultNamespace) #>