context: //
  // SharedProject.cs
  //
  // Author:
  //       Lluis Sanchez <lluis@xamarin.com>
  //
  // Copyright (c) 2014 Xamarin Inc
  //
  // Permission is hereby granted, free of charge, to any person obtaining a copy
  // of this software and associated documentation files (the "Software"), to deal
  // in the Software without restriction, including without limitation the rights
  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  // copies of the Software, and to permit persons to whom the Software is
  // furnished to do so, subject to the following conditions:
  //
  // The above copyright notice and this permission notice shall be included in
  // all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  // THE SOFTWARE.
  
  using System;
  using System.Linq;
  using System.Collections.Generic;
  using MonoDevelop.Core;
  using System.IO;
  using System.Xml;
  using MonoDevelop.Projects.Policies;
  using System.Threading.Tasks;
  using MonoDevelop.Projects.MSBuild;
  
  namespace MonoDevelop.Projects.SharedAssetsProjects
  {
  	[ExportProjectType ("{D954291E-2A0B-460D-934E-DC6B0785DB48}", Extension="shproj", Alias="SharedAssetsProject")]
  	public sealed class SharedAssetsProject: Project, IDotNetFileContainer
  	{
  		Solution currentSolution;
  		LanguageBinding languageBinding;
  		string languageName;
  		FilePath projItemsPath;
  		MSBuildProject projitemsProject;
  		HashSet<MSBuildItem> usedMSBuildItems = new HashSet<MSBuildItem> ();
  
  		const string CSharptargets = @"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets";
  		const string FSharptargets = @"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.FSharp.targets";
  
  		public SharedAssetsProject ()
  		{
  			Initialize (this);
  		}
  
  		public SharedAssetsProject (string language): this ()
  		{
  			languageName = language;
  		}
  
  		protected override void OnNameChanged (SolutionItemRenamedEventArgs e)
  		{
  			if (!projItemsPath.IsNullOrEmpty && Path.GetFileNameWithoutExtension (e.OldName) == projItemsPath.FileNameWithoutExtension) {
  				// We are going to rename the projitems file, but before that, let's get all referencing projects, since they reference
  				// using the old path
  				string oldPath = ProjItemsPath;
  				var refProjects = GetReferencingProjects ().ToArray ();
  
  				// Set the new projitems file name
  				projItemsPath = projItemsPath.ParentDirectory.Combine (e.NewName) + projItemsPath.Extension;
  
  				// Update all referencing projects
  				foreach (var p in refProjects) {
  					var sr = p.References.FirstOrDefault (r => r.GetItemsProjectPath () == oldPath);
  					if (sr != null)
  						sr.SetItemsProjectPath (ProjItemsPath);
  				}
  			}
  			base.OnNameChanged (e);
  		}
  
  		protected override void OnInitializeFromTemplate (ProjectCreateInformation projectCreateInfo, XmlElement projectOptions)
  		{
  			// Get the language before calling OnInitializeFromTemplate so the language binding
  			// is available when adding new files to the project if the project is added to
  			// an existing solution.
  			languageName = projectOptions.GetAttribute ("language");
  
  			base.OnInitializeFromTemplate (projectCreateInfo, projectOptions);
  
  			string templateDefaultNamespace = GetDefaultNamespace (projectCreateInfo, projectOptions);
  			DefaultNamespace = templateDefaultNamespace ?? projectCreateInfo.ProjectName;
  		}
  
  		static string GetDefaultNamespace (ProjectCreateInformation projectCreateInfo, XmlElement projectOptions)
  		{
  			string defaultNamespace = projectOptions.Attributes["DefaultNamespace"]?.Value;
  			if (defaultNamespace != null)
  				return StringParserService.Parse (defaultNamespace, projectCreateInfo.Parameters);
  
  			return null;
  		}
  
  		protected override void OnReadProject (ProgressMonitor monitor, MSBuildProject msproject)
  		{
  			base.OnReadProject (monitor, msproject);
  
  			var import = msproject.Imports.FirstOrDefault (im => im.Label == "Shared");
  			if (import == null)
  				return;
  
  			// TODO: load the type from msbuild
  			foreach (var item in msproject.Imports) {
  				if (item.Project.Equals (CSharptargets, StringComparison.OrdinalIgnoreCase)) {
  					LanguageName = "C#";
  					break;
  				}
  				if (item.Project.Equals (FSharptargets, StringComparison.OrdinalIgnoreCase)) {
  					LanguageName = "F#";
  					break;
  				}
  			}
  			//If for some reason the language name is empty default it to C#
  			if (String.IsNullOrEmpty(LanguageName))
  				LanguageName = "C#";
  
  			projItemsPath = MSBuildProjectService.FromMSBuildPath (msproject.BaseDirectory, import.Project);
  
  			MSBuildProject p = new MSBuildProject (msproject.EngineManager);
  			p.Load (projItemsPath);
  			p.Evaluate ();
  
  			var cp = p.PropertyGroups.FirstOrDefault (g => g.Label == "Configuration");
  			if (cp != null)
  				DefaultNamespace = cp.GetValue ("Import_RootNamespace");
  
  			LoadProjectItems (p, ProjectItemFlags.None, usedMSBuildItems);
  
  			projitemsProject = p;
  		}
  
  		internal override void SaveProjectItems (ProgressMonitor monitor, MSBuildProject msproject, HashSet<MSBuildItem> loadedItems, string pathPrefix)
  		{
  			// Save project items in the .projitems file
  			base.SaveProjectItems (monitor, projitemsProject, usedMSBuildItems, "$(MSBuildThisFileDirectory)");
  		}
  
  		protected override void OnWriteProject (ProgressMonitor monitor, MonoDevelop.Projects.MSBuild.MSBuildProject msproject)
  		{
  			if (projItemsPath == FilePath.Null)
  				projItemsPath = Path.ChangeExtension (FileName, ".projitems");
  
  			if (projitemsProject == null) {
  				projitemsProject = new MSBuildProject (msproject.EngineManager);
  				projitemsProject.FileName = projItemsPath;
  				var grp = projitemsProject.GetGlobalPropertyGroup ();
  				if (grp == null)
  					grp = projitemsProject.AddNewPropertyGroup (false);
  				grp.SetValue ("MSBuildAllProjects", "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)");
  				grp.SetValue ("HasSharedItems", true);
  				grp.SetValue ("SharedGUID", ItemId, preserveExistingCase:true);
  			}
  
  			IMSBuildPropertySet configGrp = projitemsProject.PropertyGroups.FirstOrDefault (g => g.Label == "Configuration");
  			if (configGrp == null) {
  				configGrp = projitemsProject.AddNewPropertyGroup (true);
  				configGrp.Label = "Configuration";
  			}
  			configGrp.SetValue ("Import_RootNamespace", DefaultNamespace);
  
  			base.OnWriteProject (monitor, msproject);
  
  			var newProject = FileName == null || projitemsProject.IsNewProject;
  			if (newProject) {
  				var grp = msproject.GetGlobalPropertyGroup ();
  				if (grp == null)
  					grp = msproject.AddNewPropertyGroup (false);
  				grp.SetValue ("ProjectGuid", ItemId, preserveExistingCase:true);
  				var import = msproject.AddNewImport (@"$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props");
  				import.Condition = @"Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')";
  				msproject.AddNewImport (@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props");
  				msproject.AddNewImport (@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props");
  				import = msproject.AddNewImport (MSBuildProjectService.ToMSBuildPath (FileName.ParentDirectory, projItemsPath));
  				import.Label = "Shared";
  				if (LanguageName.Equals("C#", StringComparison.OrdinalIgnoreCase)) {
  					msproject.AddNewImport (CSharptargets);
  				}
  				else if (LanguageName.Equals("F#", StringComparison.OrdinalIgnoreCase)) {
  					msproject.AddNewImport (FSharptargets);
  				}
  
  			} else {
  				var itemsImport = msproject.Imports.FirstOrDefault (i => i.Label == "Shared");
  				if (itemsImport != null)
  					itemsImport.Project = MSBuildProjectService.ToMSBuildPath (FileName.ParentDirectory, projItemsPath);
  				else {
  					var import = msproject.AddNewImport (MSBuildProjectService.ToMSBuildPath (FileName.ParentDirectory, projItemsPath));
  					import.Label = "Shared";
  				}
  			}
  
  			// having no ToolsVersion is equivalent to 2.0, roundtrip that correctly
  
gt: 			if (ToolsVersion != "2.0")