/*
		 * Check for warnings and errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
			/*
			 * If multiple distribution platform share the same name
			 */
			int duplicateCount = m_distributionPlatformList.GroupBy(x => x.name).Where(x => x.Count() > 1).Count();
			if (duplicateCount != 0)
			{
				errorReporter.addError("Each distribution platform must have a distinct name.");
			}

			/*
			 * If a distribution platform name is Default
			 */
			bool hasDefault = m_distributionPlatformList.Where(x => x.name.Equals("Default")).Count() != 0;
			if (hasDefault)
			{
				errorReporter.addError("A distribution platform can't have the name 'Default'. It is reserved for Advanced Builder, sorry...");
			}

			/*
			 * If a distribution platform name is Default
			 */
			bool isNameIncorrect = m_distributionPlatformList.Where(x => !x.isNameValid()).Count() != 0;
			if (isNameIncorrect)
			{
				errorReporter.addError("A distribution platform name can only have letters, numbers and spaces.");
			}
		}
		/*
		 * Check for warnings and errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
			if (!isBundleVersionFormatValid())
			{
				errorReporter.addError("Bundle Version has bad format\nMust be xx.xx or xx.xx.xx\n(x can be 1 or 2 digits)");
			}
		}
		/*
		 * Return specific platform errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
			AdvancedBuilder advancedBuilder = (AdvancedBuilder)AssetDatabase.LoadAssetAtPath("Assets/PygmyMonkey/AdvancedBuilder/Editor/AdvancedBuilder.asset", typeof(AdvancedBuilder));
			
			if (advancedBuilder.getAdvancedSettings().checkAndroidKeystorePasswords)
			{
				if (PlayerSettings.keystorePass.Length == 0)
				{
					errorReporter.addError("You need to define your Android Keystore password in Edit -> Project Settings -> Player -> Android -> Publishing Settings.");
				}
				else if (PlayerSettings.keyaliasPass.Length == 0)
				{
					errorReporter.addError("You need to define your Android Alias password in Edit -> Project Settings -> Player -> Android -> Publishing Settings.");
				}
			}
		}
		/*
		 * Check for warnings and errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
			PlatformProperties platformProperties = m_platform.getPlatformProperties();

			DistributionsPlatformRenderer distributionsPlatformRenderer = new DistributionsPlatformRenderer(platformProperties.getDistributionPlatformList());
			distributionsPlatformRenderer.checkWarningsAndErrors(errorReporter);

			if (platformProperties.getActivePlatformArchitectureList().Count == 0)
			{
				errorReporter.addWarning("No build will be performed for the platform '" + platformProperties.name + "'\nYou must select at least one platform architecture for this platform.");
			}
			else if (platformProperties.getActiveTextureCompressionList().Count == 0)
			{
				errorReporter.addWarning("No build will be performed for the platform '" + platformProperties.name + "'\nYou must select at least one texture compression for this platform.");
			}

			if (m_platformAdditionalRenderer != null)
			{
				m_platformAdditionalRenderer.checkWarningsAndErrors(errorReporter);
			}
		}
		/*
		 * Check for warnings and errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
			if (!m_releaseType.isActive)
			{
				return;
			}

			if (!isNameValid())
			{
				errorReporter.addError("You must specify a name for each release type.");
			}
			
			if (!isBundleIdentifierValid())
			{
				errorReporter.addError("You must specify a bundleIndentifier for the release type '" + m_releaseType.name + "'.");
			}
			
			if (!isProductNameValid())
			{
				errorReporter.addError("You must specify a product name for the release type '" + m_releaseType.name + "'.");
			}
		}
		/*
		 * Check for warnings and errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
			foreach (ReleaseType releaseType in m_releaseTypes.getReleaseTypeList())
			{
				ReleaseTypeRenderer releaseTypeRenderer = new ReleaseTypeRenderer(releaseType);
				releaseTypeRenderer.checkWarningsAndErrors(errorReporter);
			}

			/*
			 * If no release type is added
			 */
			if (m_releaseTypes.getReleaseTypeList().Count == 0)
			{
				errorReporter.addError("You need to have at least one release type.");
			}
			else
			{
				/*
				 * If no release type is active
				 */
				if (!m_releaseTypes.getReleaseTypeList().Any(x => x.isActive))
				{
					errorReporter.addError("You need to have at least one release type selected.");
				}


				/*
				 * If multiple release type share the same name
				 */
				int duplicateCount = m_releaseTypes.getReleaseTypeList().GroupBy(x => x.name).Where(x => x.Count() > 1).Count();
				if (duplicateCount != 0)
				{
					errorReporter.addError("Each release type must have a distinct name.");
				}
			}
		}
		/*
		 * Return specific platform errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
		}
		/*
		 * Check for warnings and errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
			if (!isCustomPathValid())
			{
				errorReporter.addError("Custom Path in AdvancedSettings has bad format. It must not contain $ (except for the AdvancedBuilder constants).");
			}

			if (!isCustomFileNameValid())
			{
				errorReporter.addError("Custom File Name in AdvancedSettings has bad format. It must not contain $ (except for the AdvancedBuilder constants), / or \\.");
			}

			if (!isCustomBuildMonoScriptValid())
			{
				errorReporter.addError("Your custom build script must implements the interface IAdvancedCustomBuild.");
			}
		}
		/*
		 * Check for warnings and errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
			IEnumerable<KeyValuePair<IPlatform, PlatformRenderer>> supportedPlatformList = getSupportedPlatformRenderers();

			foreach (KeyValuePair<IPlatform, PlatformRenderer> supportedPlatform in supportedPlatformList)
			{
				PlatformRenderer platformRenderer = supportedPlatform.Value;
				platformRenderer.checkWarningsAndErrors(errorReporter);
			}

			/*
			 * If no platform is selected at all
			 */
			if (supportedPlatformList.Count() == 0)
			{
				errorReporter.addError("You need to add at least on platform in the 'Platforms' section.");
			}
			else
			{
				/*
				 * If no distributionplatform is activated at all
				 */
				int totalDistributionPlatformUsedCount = m_platforms.platformDictionary.Values.Where(x => x.getPlatformProperties().isSupported()).Sum(x => x.getPlatformProperties().getActiveDistributionPlatformList().Count);
				if (totalDistributionPlatformUsedCount == 0)
				{
					errorReporter.addError("No batch build will be performed\nYou must have at least one distribution platform selected.");
				}


				/*
				 * If no platform architecture is activated at all
				 */
				int totalPlatformArchitectureUsedCount = m_platforms.platformDictionary.Values.Where(x => x.getPlatformProperties().isSupported()).Sum(x => x.getPlatformProperties().getActivePlatformArchitectureList().Count);
				
				if (totalPlatformArchitectureUsedCount == 0)
				{
					errorReporter.addError("No batch build will be performed\nYou must have at least one platform architecture selected, see warnings.");
				}


				/*
				 * If no textureCompression is activated at all
				 */
				int totalTextureCompressionUsedCount = m_platforms.platformDictionary.Values.Where(x => x.getPlatformProperties().isSupported()).Sum(x => x.getPlatformProperties().getActiveTextureCompressionList().Count);

				if (totalTextureCompressionUsedCount == 0)
				{
					errorReporter.addError("No batch build will be performed\nYou must have at least one texture compression selected, see warnings.");
				}
			}
		}
		public bool drawInspector()
		{
			ErrorReporter errorReporter = new ErrorReporter();
			
			// -------------------
			// Product parameters
			// -------------------
			ProductParametersRenderer productParametersRenderer = new ProductParametersRenderer(m_advancedBuilder.getProductParameters());
			productParametersRenderer.checkWarningsAndErrors(errorReporter);

			if (GUIUtils.DrawHeader("Product Parameters", "ab_product_parameters"))
			{
				GUIUtils.BeginContents();
				productParametersRenderer.drawInspector();
				GUIUtils.EndContents();
			}
			
			
			
			// --------------
			// Release Types
			// --------------
			ReleaseTypesRenderer releaseTypesRenderer = new ReleaseTypesRenderer(m_advancedBuilder.getReleaseTypes());
			releaseTypesRenderer.checkWarningsAndErrors(errorReporter);

			if (GUIUtils.DrawHeader("Release Types", "ab_release_types"))
			{
				GUIUtils.BeginContents();
				releaseTypesRenderer.drawInspector();
				GUIUtils.EndContents();
			}
			
			
			
			// ----------
			// Platforms
			// ----------
			PlatformsRenderer platformsRenderer = new PlatformsRenderer(m_advancedBuilder.getPlatforms());
			platformsRenderer.checkWarningsAndErrors(errorReporter);

			if (GUIUtils.DrawHeader("Platforms", "ab_platforms"))
			{
				GUIUtils.BeginContents();
				platformsRenderer.drawInspector();
				GUIUtils.EndContents();
			}



			// ------------------
			// Advanced Settings
			// ------------------
			AdvancedSettingsRenderer advancedSettingsRenderer = new AdvancedSettingsRenderer(m_advancedBuilder.getAdvancedSettings());
			advancedSettingsRenderer.checkWarningsAndErrors(errorReporter);

			if (GUIUtils.DrawHeader("Advanced Settings", "ab_advanced_settings"))
			{
				GUIUtils.BeginContents();
				advancedSettingsRenderer.drawInspector();
				GUIUtils.EndContents();
			}



			// ------------------
			// App Configuration
			// ------------------
			ProjectConfigurationsRenderer projectConfigurationsRenderer = new ProjectConfigurationsRenderer(m_advancedBuilder, m_advancedBuilder.getProjectConfigurations());
			projectConfigurationsRenderer.checkWarningsAndErrors(errorReporter);

			if (GUIUtils.DrawHeader("Project Configurations", "ab_project_configurations"))
			{
				GUIUtils.BeginContents();
				bool wasBuildProcessLaunched = projectConfigurationsRenderer.drawInspector(platformsRenderer, errorReporter);
				if (wasBuildProcessLaunched)
				{
					return true;
				}
				GUIUtils.EndContents();
			}



			// ------------------
			// Perform Build
			// ------------------
			if (GUIUtils.DrawHeader("Perform Build", "ab_perform_build", true))
			{
				GUIUtils.BeginContents();
				{
					if (errorReporter.getWarningCount() > 0 || errorReporter.getErrorCount() > 0)
					{
						foreach (string iMessage in errorReporter.getErrorList())
						{
							EditorGUILayout.HelpBox(iMessage, MessageType.Error, true);
						}

						foreach (string iMessage in errorReporter.getWarningList())
						{
							EditorGUILayout.HelpBox(iMessage, MessageType.Warning, true);
						}
					}


					bool isBuildAllowed = m_advancedBuilder.getProjectConfigurations().getTotalBuildCount() != 0 && errorReporter.getErrorCount() <= 0;
					
					
					/*
					 * Perform the build
					 */
					GUI.enabled = isBuildAllowed;
					
					if (GUIUtils.DrawBigButton("Perform a total of " + m_advancedBuilder.getProjectConfigurations().getTotalBuildCount() + " builds", Color.green))
					{
						if (m_advancedBuilder.getProjectConfigurations().getTotalAutoRunBuildCount() > 3)
						{
							if (EditorUtility.DisplayDialog("Launch build?", "You have selected the 'Autorun Build' option and you are making multiple builds, are you sure you want to continue?", "Yes", "Cancel"))
							{
								AdvancedBuilder.PerformBuild();
							}
						}
						else
						{
							AdvancedBuilder.PerformBuild();
						}

						return true;
					}
					
					GUI.enabled = true;
						
						
					/*
					 * Button to open build folder
					 */
					if (GUIUtils.DrawBigButton("Open Build folder"))
					{
						string buildFolderPath = Application.dataPath.Replace("Assets", "Builds");
						
						if (!Directory.Exists(buildFolderPath))
						{
							Directory.CreateDirectory(buildFolderPath);
						}
						
						EditorUtility.OpenWithDefaultApp(buildFolderPath);
					}
					
					GUILayout.Space(5f);
				}
				GUIUtils.EndContents();
			}

			return false;
		}
		private bool drawSelectedConfigurationList(PlatformsRenderer platformsRenderer, ErrorReporter errorReporter)
		{
			EditorGUILayout.HelpBox("Here you can switch to a configuration, so you can directly test your game inside the Editor in the configuration you want. Of course if you decide to build, every build will have the configuration you specified. You can click on a configuration to see details and apply specific parameters.", MessageType.Info, true);
			GUILayout.BeginVertical();
			{
				for (int i = 0; i < m_projectConfigurations.configurationList.Count; i++)
				{
					Configuration configuration = m_projectConfigurations.configurationList[i];
					
					// If we could not find the texture compression, it's because we loaded AdvancedBuilder with an older version of Unity used to create the AdvancedBuilder data
					if (configuration.textureCompression == null)
					{
						m_projectConfigurations.configurationList.Remove(configuration);
						return false;
					}
					
					EditorGUILayout.BeginHorizontal();
					{
						configuration.isEnabled = EditorGUILayout.Toggle(configuration.isEnabled, GUILayout.Width(15f));

						GUI.backgroundColor = m_projectConfigurations.selectedConfigurationIndex == i ? Color.green : Color.white;
						if (GUILayout.Button(configuration.ToString()))
						{
							ConfigurationSceneRenderer.ComputeProjectSceneList();
							m_configurationSceneRenderer.updateAvailableSceneList(configuration);

							if (m_projectConfigurations.selectedConfigurationIndex == i)
							{
								m_projectConfigurations.selectedConfigurationIndex = -1;
							}
							else
							{
								m_projectConfigurations.selectedConfigurationIndex = i;
							}

							GUI.FocusControl(null);
						}
						GUI.backgroundColor = Color.white;

						GUI.backgroundColor = Color.red;
						if (GUILayout.Button("x", GUILayout.Width(25f)))
						{
							m_projectConfigurations.selectedConfigurationIndex = -1;
							m_projectConfigurations.configurationList.Remove(configuration);
							return false;
						}
						GUI.backgroundColor = Color.white;
					}
					EditorGUILayout.EndHorizontal();

					if (m_projectConfigurations.selectedConfigurationIndex == i)
					{
						GUILayout.Space(5);

						bool hasPressBuild = drawConfigurationDetail(platformsRenderer, errorReporter);
						if (hasPressBuild)
						{
							return true;
						}
						
						GUILayout.Space(10);
					}
				}
			}
			GUILayout.EndVertical();

			return false;
		}
		public bool drawInspector(PlatformsRenderer platformsRenderer, ErrorReporter errorReporter)
		{
			List<Configuration> configurationList = m_projectConfigurations.getAvailableConfigurationList(m_advancedBuilder.getReleaseTypes(), m_advancedBuilder.getPlatforms());
			drawAvailableConfigurationList(configurationList);
			return drawSelectedConfigurationList(platformsRenderer, errorReporter);
		}
		/*
		 * Check for warnings and errors
		 */
		public void checkWarningsAndErrors(ErrorReporter errorReporter)
		{
			if (m_advancedBuilder.getAdvancedSettings().overwriteScenes)
			{
				foreach (Configuration configuration in m_projectConfigurations.configurationList)
				{
					if (configuration.scenePathList == null || configuration.scenePathList.Count == 0)
					{
						errorReporter.addError("The configuration " + configuration.ToString() + " has no scene defined");
					}
				}
			}
			else
			{
				if (Utils.GetActiveScenePathArray() == null || Utils.GetActiveScenePathArray().Length == 0)
				{
					errorReporter.addError("You need at least one active scene for your project. Check File -> Build Settings");
				}
			}

			#if !UNITY_EDITOR_OSX
			if (m_projectConfigurations.configurationList.Count(x => x.platformType.Equals(PlatformType.iOS) && x.shouldAutoRunPlayer) != 0)
			{
				errorReporter.addError("You can't autorun an iOS build because you're not using a Mac. You can still build for iOS, but can't autorun. Please uncheck the 'Autorun Build' box in your build configuration");
			}
			#endif

			List<ReleaseType> activeReleaseTypeList = m_advancedBuilder.getReleaseTypes().getReleaseTypeList().Where(x => x.isActive).ToList();
			
			if (activeReleaseTypeList.Count == 0)
			{
				errorReporter.addWarning("You need to select at least one release type in the 'Release Type' window.");
			}

			if (m_projectConfigurations.configurationList.Count == 0)
			{
				errorReporter.addWarning("You need to add at least one configuration in order to build multiple configurations.");
			}
			else
			{
				if (m_projectConfigurations.configurationList.Count(x => x.isEnabled) == 0)
				{
					errorReporter.addWarning("You need to enable at least one configuration in order to build multiple configurations.");
				}

				if (m_projectConfigurations.configurationList.GroupBy(x => x.getBuildPath(m_advancedBuilder.getAdvancedSettings(), System.DateTime.Now, m_advancedBuilder.getProductParameters().bundleVersion)).SelectMany(group => group.Skip(1)).Count() != 0)
				{
					errorReporter.addError("Be careful. You have some build path that are exactly the same for some configuration. So one configuration build will erase the other! Please modify the build path in the 'Build folder path' section to avoid this!");
				}

				foreach (Configuration configuration in m_projectConfigurations.configurationList)
				{
					string finalBuildPath = Application.dataPath.Replace("/Assets", string.Empty) + configuration.getBuildPath(m_advancedBuilder.getAdvancedSettings(), System.DateTime.Now, m_advancedBuilder.getProductParameters().bundleVersion);
					if (File.Exists(finalBuildPath) || Directory.Exists(finalBuildPath))
					{
						errorReporter.addWarning("There is already a build at path " + finalBuildPath + " for the configuration " + configuration.getDescription() + ". If you build, it will overwrite it.");
					}
				}
			}

			foreach (Configuration configuration in m_projectConfigurations.configurationList)
			{
				if (m_advancedBuilder.getReleaseTypes().getReleaseTypeList().Where(x => x.name.Equals(configuration.releaseType.name)).Count() == 0)
				{
					errorReporter.addWarning("Be careful, it seems you changed a release type name, and your configuration " + configuration.getDescription() + " still uses the old one (" + (configuration.releaseType == null ? "N/A" : configuration.releaseType.name) + "). To update, please delete the configuration and add it back again (remember to save your custom defines)");
				}

				if (m_advancedBuilder.getReleaseTypes().getReleaseTypeList().Where(x => x.bundleIdentifier.Equals(configuration.releaseType.bundleIdentifier)).Count() == 0)
				{
					errorReporter.addWarning("Be careful, it seems you changed a release type bundle identifier, and your configuration " + configuration.getDescription() + " still uses the old one (" + (configuration.releaseType == null ? "N/A" : configuration.releaseType.bundleIdentifier) + "). To update, please delete the configuration and add it back again (remember to save your custom defines)");
				}
				
				if (m_advancedBuilder.getReleaseTypes().getReleaseTypeList().Where(x => x.productName.Equals(configuration.releaseType.productName)).Count() == 0)
				{
					errorReporter.addWarning("Be careful, it seems you changed a release type product name, and your configuration " + configuration.getDescription() + " still uses the old one (" + (configuration.releaseType == null ? "N/A" : configuration.releaseType.productName) + "). To update, please delete the configuration and add it back again (remember to save your custom defines)");
				}

				if (!configuration.distributionPlatform.name.Equals("Default"))
				{
					if (configuration.platform.getPlatformProperties().getDistributionPlatformList().Where(x => x.name.Equals(configuration.distributionPlatform.name)).Count() == 0)
					{
						errorReporter.addWarning("Be careful, it seems you changed a distribution platform name, and your configuration " + configuration.getDescription() + " still uses the old one (" + (configuration.distributionPlatform == null ? "N/A" : configuration.distributionPlatform.name) + "). To update, please delete the configuration and add it back again (remember to save your custom defines)");
					}
				}
			}
		}
		private bool drawConfigurationDetail(PlatformsRenderer platformsRenderer, ErrorReporter errorReporter)
		{
			if (m_projectConfigurations.selectedConfigurationIndex >= m_projectConfigurations.configurationList.Count)
			{
				m_projectConfigurations.selectedConfigurationIndex = -1;
				return false;
			}

			Configuration configuration = m_projectConfigurations.configurationList[m_projectConfigurations.selectedConfigurationIndex];

			if (GUIUtils.DrawHeader("Configuration information", true))
			{
				GUIUtils.BeginContents();
				
				GUILayout.BeginHorizontal();
				{
					GUILayout.BeginVertical();
					{
						configuration.name = EditorGUILayout.TextField("Name:", configuration.name);

						EditorGUILayout.LabelField("Default Defines:", configuration.getDefines());
						configuration.customDefines = EditorGUILayout.TextField("Custom Defines:", configuration.customDefines);

						if (configuration.platformType == PlatformType.WindowsStore)
						{
							if (PlatformWindowsStore.IsUniversal(configuration.platformArchitecture.name))
							{
								configuration.wsaBuildAndRunDeployTarget = (WSABuildAndRunDeployTarget)EditorGUILayout.EnumPopup("Build and Deploy Target", configuration.wsaBuildAndRunDeployTarget);
							}
						}

						/*if (configuration.platformType == PlatformType.Android)
						{
							configuration.appendProject = EditorGUILayout.ToggleLeft(new GUIContent("Append project", "(Used when building Eclipse project) This setting will create a new Eclipse project. Existing Eclipse project setting changes will be discarded."), configuration.appendProject);
						}
						else */if (configuration.platformType == PlatformType.iOS)
						{
							configuration.appendProject = EditorGUILayout.ToggleLeft(new GUIContent("Append project", "This setting will append an existing Xcode project. Existing Xcode project setting changes will be preserved."), configuration.appendProject);
						}
						else if (configuration.platformType == PlatformType.WindowsStore)
						{
							configuration.appendProject = EditorGUILayout.ToggleLeft(new GUIContent("Append project", "This setting will append an existing project instead of replacing it."), configuration.appendProject);
						}

						configuration.openBuildFolder = EditorGUILayout.ToggleLeft("Open build folder after build", configuration.openBuildFolder);
						configuration.isDevelopmentBuild = EditorGUILayout.ToggleLeft("Development build", configuration.isDevelopmentBuild);
						configuration.shouldAutoconnectProfiler = EditorGUILayout.ToggleLeft("Autoconnect Profiler", configuration.shouldAutoconnectProfiler);
						configuration.allowDebugging = EditorGUILayout.ToggleLeft("Allow script debugging", configuration.allowDebugging);
						configuration.shouldAutoRunPlayer = EditorGUILayout.ToggleLeft("Autorun Build", configuration.shouldAutoRunPlayer);

						m_configurationSceneRenderer.drawInspector(configuration);

						if (GUIUtils.DrawHeader("Build information"))
						{
							GUIUtils.BeginContents();
							{
								PlatformRenderer platformRenderer = platformsRenderer.getPlatformRendererFromPlatform(configuration.platform.getPlatformProperties().platformType);
								platformRenderer.drawBuildSummary(m_advancedBuilder.getAdvancedSettings(), configuration, m_advancedBuilder.getProductParameters().bundleVersion);
							}
							GUIUtils.EndContents();
						}
						
						GUILayout.BeginHorizontal();
						{
							if (GUILayout.Button("Apply this config" + (m_projectConfigurations.isCurrentConfig(configuration) ? " (Current)" : "")))
							{
								configuration.applyConfiguration();
							}

							GUI.enabled = errorReporter.getErrorCount() == 0;
							if (GUILayout.Button("Build"))
							{
								AdvancedBuilder.PerformBuild(configuration);
								return true;
							}
							GUI.enabled = true;
						}
						GUILayout.EndHorizontal();
					}
					GUILayout.EndVertical();
				}
				GUILayout.EndHorizontal();
				
				GUIUtils.EndContents();
			}

			return false;
		}