/// <summary>
        /// Loads the definition contents asynchronous.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="path">The path.</param>
        /// <returns>Task&lt;System.String&gt;.</returns>
        public Task <string> LoadDefinitionContentsAsync(ModPatchExporterParameters parameters, string path)
        {
            var patchPath = Path.Combine(parameters.RootPath, parameters.PatchName, path);

            if (File.Exists(patchPath))
            {
                return(File.ReadAllTextAsync(patchPath));
            }
            return(Task.FromResult(string.Empty));
        }
        /// <summary>
        /// export definition as an asynchronous operation.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <returns>Task&lt;System.Boolean&gt;.</returns>
        /// <exception cref="ArgumentNullException">Game.</exception>
        /// <exception cref="ArgumentNullException">Definitions.</exception>
        public async Task <bool> ExportDefinitionAsync(ModPatchExporterParameters parameters)
        {
            if (string.IsNullOrWhiteSpace(parameters.Game))
            {
                throw new ArgumentNullException("Game.");
            }
            var definitionsInvalid = (parameters.Definitions == null || parameters.Definitions.Count() == 0) &&
                                     (parameters.OrphanConflicts == null || parameters.OrphanConflicts.Count() == 0) &&
                                     (parameters.OverwrittenConflicts == null || parameters.OverwrittenConflicts.Count() == 0) &&
                                     (parameters.CustomConflicts == null || parameters.CustomConflicts.Count() == 0);

            if (definitionsInvalid)
            {
                throw new ArgumentNullException("Definitions.");
            }
            var definitionInfoProvider = definitionInfoProviders.FirstOrDefault(p => p.CanProcess(parameters.Game));

            if (definitionInfoProvider != null)
            {
                var results = new List <bool>();

                if (parameters.Definitions?.Count() > 0)
                {
                    results.Add(await CopyBinariesAsync(parameters.Definitions.Where(p => p.ValueType == Parser.Common.ValueType.Binary),
                                                        GetPatchRootPath(parameters.RootPath, parameters.PatchName), false));
                    results.Add(await WriteMergedContentAsync(parameters.Definitions.Where(p => p.ValueType != Parser.Common.ValueType.Binary),
                                                              GetPatchRootPath(parameters.RootPath, parameters.PatchName), parameters.Game, false, FileNameGeneration.GenerateFileName));
                }

                if (parameters.OrphanConflicts?.Count() > 0)
                {
                    results.Add(await CopyBinariesAsync(parameters.OrphanConflicts.Where(p => p.ValueType == Parser.Common.ValueType.Binary),
                                                        GetPatchRootPath(parameters.RootPath, parameters.PatchName), false));
                    results.Add(await WriteMergedContentAsync(parameters.OrphanConflicts.Where(p => p.ValueType != Parser.Common.ValueType.Binary),
                                                              GetPatchRootPath(parameters.RootPath, parameters.PatchName), parameters.Game, false, FileNameGeneration.GenerateFileName));
                }

                if (parameters.OverwrittenConflicts?.Count() > 0)
                {
                    results.Add(await CopyBinariesAsync(parameters.OverwrittenConflicts.Where(p => p.ValueType == Parser.Common.ValueType.Binary),
                                                        GetPatchRootPath(parameters.RootPath, parameters.PatchName), false));
                    results.Add(await WriteMergedContentAsync(parameters.OverwrittenConflicts.Where(p => p.ValueType != Parser.Common.ValueType.Binary),
                                                              GetPatchRootPath(parameters.RootPath, parameters.PatchName), parameters.Game, false, FileNameGeneration.UseExistingFileNameAndWriteEmptyFiles));
                }

                if (parameters.CustomConflicts?.Count() > 0)
                {
                    results.Add(await WriteMergedContentAsync(parameters.CustomConflicts.Where(p => p.ValueType != Parser.Common.ValueType.Binary),
                                                              GetPatchRootPath(parameters.RootPath, parameters.PatchName), parameters.Game, true, FileNameGeneration.UseExistingFileName));
                }
                return(results.All(p => p));
            }
            return(false);
        }
        /// <summary>
        /// rename patch mod as an asynchronous operation.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <returns>Task&lt;System.Boolean&gt;.</returns>
        public async Task <bool> RenamePatchModAsync(ModPatchExporterParameters parameters)
        {
            var result = await CopyPathModInternalAsync(parameters);

            if (result)
            {
                var oldPath = Path.Combine(parameters.RootPath, parameters.ModPath);
                if (Directory.Exists(oldPath))
                {
                    Directory.Delete(oldPath, true);
                }
            }
            return(result);
        }
        /// <summary>
        /// Gets the patch files.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <returns>IEnumerable&lt;System.String&gt;.</returns>
        public IEnumerable <string> GetPatchFiles(ModPatchExporterParameters parameters)
        {
            var path  = GetPatchRootPath(parameters.RootPath, parameters.PatchName);
            var files = new List <string>();

            if (Directory.Exists(path))
            {
                foreach (var item in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
                {
                    var relativePath = item.Replace(path, string.Empty).Trim(Path.DirectorySeparatorChar);
                    if (relativePath.Contains(Path.DirectorySeparatorChar) && !relativePath.Contains(StateHistory, StringComparison.OrdinalIgnoreCase))
                    {
                        files.Add(relativePath);
                    }
                }
            }
            return(files);
        }
        /// <summary>
        /// Saves the state asynchronous.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <returns>Task&lt;System.Boolean&gt;.</returns>
        public async Task <bool> SaveStateAsync(ModPatchExporterParameters parameters)
        {
            var state = await GetPatchStateInternalAsync(parameters, true);

            if (state == null)
            {
                state = DIResolver.Get <IPatchState>();
            }
            var modifiedHistory = new List <IDefinition>();
            var path            = Path.Combine(GetPatchRootPath(parameters.RootPath, parameters.PatchName));

            state.IgnoreConflictPaths  = parameters.IgnoreConflictPaths;
            state.ResolvedConflicts    = MapDefinitions(parameters.ResolvedConflicts, false);
            state.Conflicts            = MapDefinitions(parameters.Conflicts, false);
            state.OrphanConflicts      = MapDefinitions(parameters.OrphanConflicts, false);
            state.IgnoredConflicts     = MapDefinitions(parameters.IgnoredConflicts, false);
            state.OverwrittenConflicts = MapDefinitions(parameters.OverwrittenConflicts, false);
            state.CustomConflicts      = MapDefinitions(parameters.CustomConflicts, false);
            state.Mode = parameters.Mode;
            var history = state.ConflictHistory != null?state.ConflictHistory.ToList() : new List <IDefinition>();

            var indexed = DIResolver.Get <IIndexedDefinitions>();

            indexed.InitMap(history);
            if (parameters.ResolvedConflicts != null)
            {
                foreach (var item in parameters.ResolvedConflicts.Where(s => !string.IsNullOrWhiteSpace(s.Code)))
                {
                    var existingHits = indexed.GetByTypeAndId(item.TypeAndId).ToList();
                    var existing     = existingHits.FirstOrDefault(p => item.Code.Equals(p.Code));
                    if (existing == null)
                    {
                        history.RemoveAll(p => existingHits.Any(x => p.Equals(x)));
                        history.Add(item);
                        modifiedHistory.Add(item);
                    }
                    else
                    {
                        existingHits.Remove(existing);
                        history.RemoveAll(p => existingHits.Any(x => p.Equals(x)));
                    }
                }
            }
            if (parameters.Definitions != null)
            {
                foreach (var item in parameters.Definitions.Where(s => !string.IsNullOrWhiteSpace(s.Code) && !modifiedHistory.Any(p => p.TypeAndId.Equals(s.TypeAndId))))
                {
                    var existingHits = indexed.GetByTypeAndId(item.TypeAndId).ToList();
                    history.RemoveAll(p => existingHits.Any(x => p.Equals(x)));
                    history.Add(item);
                    modifiedHistory.Add(item);
                }
            }
            state.ConflictHistory = MapDefinitions(history, true);
            var externallyLoadedCode = cache.Get <HashSet <string> >(CacheStatePrefix, CacheExternalCodeKey);

            if (externallyLoadedCode == null)
            {
                externallyLoadedCode = new HashSet <string>();
                cache.Set(CacheStatePrefix, CacheExternalCodeKey, externallyLoadedCode);
            }
            return(StoreState(state, modifiedHistory, externallyLoadedCode, path));
        }
 /// <summary>
 /// get patch state as an asynchronous operation.
 /// </summary>
 /// <param name="parameters">The parameters.</param>
 /// <param name="loadExternalCode">if set to <c>true</c> [load external code].</param>
 /// <returns>IPatchState.</returns>
 public async Task <IPatchState> GetPatchStateAsync(ModPatchExporterParameters parameters, bool loadExternalCode = true)
 {
     return(await GetPatchStateInternalAsync(parameters, loadExternalCode));
 }
 /// <summary>
 /// Copies the patch mod asynchronous.
 /// </summary>
 /// <param name="parameters">The parameters.</param>
 /// <returns>Task&lt;System.Boolean&gt;.</returns>
 public Task <bool> CopyPatchModAsync(ModPatchExporterParameters parameters)
 {
     return(CopyPathModInternalAsync(parameters));
 }