<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <UsingTask TaskName="PrereleaseResolveNuGetPackageAssets" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
  <UsingTask TaskName="ValidateProjectDependencyVersions" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>

  <PropertyGroup>
    <ProjectJson Condition="'$(ProjectJson)'=='' and Exists('$(MSBuildProjectDirectory)/project.json')">$(MSBuildProjectDirectory)/project.json</ProjectJson>
    <ProjectLockJson Condition="Exists('$(ProjectJson)') and '$(ProjectLockJson)'==''">$(MSBuildProjectDirectory)/project.lock.json</ProjectLockJson>
    <ResolveNugetProjectFile Condition="'$(ResolveNugetProjectFile)' == ''">$(MSBuildProjectFullPath)</ResolveNugetProjectFile>
    <RestorePackages Condition="'$(RestorePackages)'!='false' and Exists('$(ProjectJson)') and '$(DesignTimeBuild)' != 'true'">true</RestorePackages>
    <PrereleaseResolveNuGetPackages Condition="'$(PrereleaseResolveNuGetPackages)'!='false' and Exists('$(ProjectJson)')">true</PrereleaseResolveNuGetPackages>

    <!--
        For now, prevent built-in task (if available) from running.
        More changes are needed to light up on their availability
        and use them instead of what we have here. See buildtools
        issue #192.
     -->
    <ResolveNugetPackages>false</ResolveNugetPackages>
  </PropertyGroup>

  <!-- Restoring packages during a background (designtime) build will cause VS 2015 (v14) to get into an endless loop of resolving references. -->
  <Target Name="RestorePackages"
          BeforeTargets="ResolveNuGetPackages;ValidatePackageVersions"
          Condition="'$(RestorePackages)'=='true' and !('$(VSDesignTimeBuild)'=='true' and '$(VisualStudioVersion)' >= '14.0')">

    <Error Condition="'$(DnuRestoreCommand)'=='' and Exists('$(ProjectJson)')" Text="RestorePackages target needs a predefined DnuRestoreCommand property set in order to restore $(ProjectJson)" />

    <Exec Condition="Exists('$(ProjectJson)')" Command="$(DnuRestoreCommand) &quot;$(ProjectJson)&quot;" StandardOutputImportance="Low" CustomErrorRegularExpression="^Unable to locate .*" />
  </Target>

  <ItemGroup Condition="'$(ResolvePackages)'=='true' or '$(PrereleaseResolveNuGetPackages)'=='true'">
    <CustomAdditionalCompileInputs Condition="Exists('$(ProjectJson)')" Include="$(ProjectJson)" />
  </ItemGroup>

  <PropertyGroup>
    <ResolveAssemblyReferencesDependsOn>
      $(ResolveAssemblyReferencesDependsOn);
      ResolveNuGetPackages;
      ValidatePackageVersions;
    </ResolveAssemblyReferencesDependsOn>

    <!-- temporarily accept the old name NuGetTargetFrameworkMoniker until all projects are moved forward -->
    <NuGetTargetMoniker Condition="'$(NuGetTargetMoniker)' == ''">$(NuGetTargetFrameworkMoniker)</NuGetTargetMoniker>
    <UseTargetPlatformAsNuGetTargetMoniker Condition="'$(UseTargetPlatformAsNuGetTargetMoniker)' == '' AND '$(TargetFrameworkMoniker)' == '.NETCore,Version=v5.0'">true</UseTargetPlatformAsNuGetTargetMoniker>
    <NuGetTargetMoniker Condition="'$(NuGetTargetMoniker)' == '' AND '$(UseTargetPlatformAsNuGetTargetMoniker)' == 'true'">$(TargetPlatformIdentifier),Version=v$([System.Version]::Parse('$(TargetPlatformMinVersion)').ToString(3))</NuGetTargetMoniker>
    <NuGetTargetMoniker Condition="'$(NuGetTargetMoniker)' == '' AND '$(UseTargetPlatformAsNuGetTargetMoniker)' != 'true'">$(TargetFrameworkMoniker)</NuGetTargetMoniker>


    <BaseNuGetRuntimeIdentifier Condition="'$(BaseNuGetRuntimeIdentifier)' == '' and '$(TargetPlatformIdentifier)' == 'UAP'">win10</BaseNuGetRuntimeIdentifier>
    <BaseNuGetRuntimeIdentifier Condition="'$(BaseNuGetRuntimeIdentifier)' == ''">win</BaseNuGetRuntimeIdentifier>
    <CopyNuGetImplementations Condition="'$(CopyNuGetImplementations)' == '' and '$(OutputType)' != 'library' and ('$(OutputType)' != 'winmdobj' or '$(AppxPackage)' == 'true')">true</CopyNuGetImplementations>
  </PropertyGroup>

  <!-- If a RuntimeIndentifier wasn't already specified, let's go generate it -->
  <PropertyGroup Condition="'$(NuGetRuntimeIdentifier)' == '' and '$(CopyNuGetImplementations)' == 'true'">
    <_NuGetRuntimeIdentifierWithoutAot>$(BaseNuGetRuntimeIdentifier)-$(PlatformTarget.ToLower())</_NuGetRuntimeIdentifierWithoutAot>
    <NuGetRuntimeIdentifier>$(_NuGetRuntimeIdentifierWithoutAot)</NuGetRuntimeIdentifier>
    <NuGetRuntimeIdentifier Condition="'$(UseDotNetNativeToolchain)' == 'true'">$(_NuGetRuntimeIdentifierWithoutAot)-aot</NuGetRuntimeIdentifier>
  </PropertyGroup>

  <Target Name="ResolveNuGetPackages"
          Condition="'$(PrereleaseResolveNuGetPackages)'=='true'">

    <PropertyGroup>
      <!-- Temporary workaround -->
      <NuGetTargetMoniker Condition="'$(NuGetTargetMoniker)' == '.NETPortable,Version=v4.5,Profile=Profile7'">DNXCore,Version=v5.0</NuGetTargetMoniker>
    </PropertyGroup>

    <PrereleaseResolveNuGetPackageAssets Condition="Exists('$(ProjectLockJson)')"
                               AllowFallbackOnTargetSelection="true"
                               IncludeFrameworkReferences="false"
                               NuGetPackagesDirectory="$(PackagesDir)"
                               RuntimeIdentifier="$(NuGetRuntimeIdentifier)"
                               ProjectLanguage="$(Language)"
                               ProjectLockFile="$(ProjectLockJson)"
                               TargetMonikers="$(NuGetTargetMoniker)">
      <Output TaskParameter="ResolvedAnalyzers" ItemName="Analyzer" />
      <Output TaskParameter="ResolvedReferences" ItemName="Reference" />
      <Output TaskParameter="ResolvedCopyLocalItems" ItemName="ReferenceCopyLocalPaths" />
      <Output TaskParameter="ReferencedPackages" ItemName="ReferencedNuGetPackages" />
    </PrereleaseResolveNuGetPackageAssets>

    <!-- We may have an indirect package reference that we want to replace with a project reference -->
    <ItemGroup>
      <!-- Intersect project-refs with package-refs -->
      <_ReferenceFileNamesToRemove Include="@(Reference)" Condition="'@(_ResolvedProjectReferencePaths->'%(FileName)%(Extension)')' == '%(FileName)%(Extension)'" />
      <_ReferenceCopyLocalPathsFileNamesToRemove Include="@(ReferenceCopyLocalPaths)" Condition="'@(_ResolvedProjectReferencePaths->'%(FileName)%(Extension)')' == '%(FileName)%(Extension)'" />

      <Reference Remove="@(_ReferenceFileNamesToRemove)" />
      <ReferenceCopyLocalPaths Remove="@(_ReferenceCopyLocalPathsFileNamesToRemove)"/>
    </ItemGroup>

    <Message Text="Excluding @(_ReferenceFileNamesToRemove);@(_ReferenceCopyLocalPathsFileNamesToRemove) from package references since the same file is provided by a project refrence."
             Condition="'@(_ReferenceFileNamesToRemove)' != '' or '@(_ReferenceCopyLocalPathsFileNamesToRemove)' != ''"/>
  </Target>

  <Target Name="RemoveTransitiveCompileReferences"
          AfterTargets="ResolveNuGetPackages">
    <ItemGroup Condition="'$(OmitTransitiveCompileReferences)' == 'true'">
      <!-- get all references from nuget packages as ID so that we can substract the direct ref IDs-->
      <_ReferenceAsPackageId Include="@(Reference->'%(NuGetPackageId)')" Condition="'%(Reference.NuGetPackageId)' != ''">
        <OriginalIdentity>%(Identity)</OriginalIdentity>
      </_ReferenceAsPackageId>

      <!-- Indirect references are any references whose PackageId isn't in the direct reference set: ReferencedNuGetPackages -->
      <_IndirectReferenceAsPackageId Include="@(_ReferenceAsPackageId)" Exclude="@(ReferencedNuGetPackages)"/>

      <!-- Transform back to original -->
      <IndirectReference Include="@(_IndirectReferenceAsPackageId->'%(OriginalIdentity)')" />

      <Reference Remove="@(IndirectReference)"/>
    </ItemGroup>
  </Target>

  <Target Name="ValidatePackageVersions"
          Condition="'$(RestorePackages)'=='true' and '$(ValidatePackageVersions)'=='true' and Exists('$(ProjectJson)')">
    <ValidateProjectDependencyVersions ProjectJsons="$(ProjectJson)"
                                       ProhibitFloatingDependencies="$(ProhibitFloatingDependencies)"
                                       ValidationPatterns="@(ValidationPattern)" />
  </Target>

  <Target Name="FilterTargetingPackResolvedNugetPackages" AfterTargets="ResolveNuGetPackages" >
    <PropertyGroup>
      <_TargetingPackPrefix>Microsoft.TargetingPack</_TargetingPackPrefix>
    </PropertyGroup>

    <!--
      Add the mscorlib and windows to the reference set by default to avoid a lot of duplication in projects
      They only act as a filter so if they aren't present in the packages references it will not impact anything.
    -->
    <ItemGroup Condition="'$(ExcludeDefaultTargetingPackReferences)' != 'true'">
      <TargetingPackReference Include="mscorlib" />
      <TargetingPackReference Include="Windows" />
    </ItemGroup>

    <ItemGroup>
      <!-- Filter out all references coming out of the targeting pack packages except for TargetingPackReferences -->
      <ResolvedTargetingPackReference Include="@(Reference)"
        Condition="$([System.String]::new('%(Reference.NuGetPackageId)').StartsWith('$(_TargetingPackPrefix)'))" />
      <ResolvedTargetingPackReferenceFilename Include="@(ResolvedTargetingPackReference -> '%(Filename)')">
        <OriginalIdentity>%(Identity)</OriginalIdentity>
      </ResolvedTargetingPackReferenceFilename>
      <ResolvedTargetingPackReferenceFilename Remove="@(TargetingPackReference)" />
      <PackageReferencesToRemove Include="@(ResolvedTargetingPackReferenceFilename -> '%(OriginalIdentity)')" />
      <Reference Remove="@(PackageReferencesToRemove)" />

      <!-- Filter out the copy-local set of references coming from the targeting pack packages -->
      <PackageCopyLocalToRemove Include="@(ReferenceCopyLocalPaths)"
        Condition="$([System.String]::new('%(ReferenceCopyLocalPaths.NuGetPackageId)').StartsWith('$(_TargetingPackPrefix)'))" />
      <ReferenceCopyLocalPaths Remove="@(PackageCopyLocalToRemove)" />
    </ItemGroup>

    <Message Importance="Low" 
             Text="Removed all ResolvedTagetingPackReferences that were not specified explicitly as a TargetingPackReference=[@(TargetingPackReference)]. PackageReferencesToRemove=[@(PackageReferencesToRemove)]." />
  </Target>
</Project>
