private void _SynchronizeFolder(String Path, double StepFrom = 0.0, double StepTo = 1.0)
        {
            //Console.WriteLine("------------{0}/{1}", StepFrom, StepTo);

            Canceling = false;

            CallStep(StepFrom, String.Format(SynchronizingFormat, Path));

            var SourceFiles = this.SourceFileSystem
                              .FindFiles(FileSystem.CombinePath(SourcePath, Path))
                              .ToDictionary(FileSystemEntry => FileSystemEntry.Name)
            ;
            var DestinationFiles = this.DestinationFileSystem
                                   .FindFiles(FileSystem.CombinePath(DestinationPath, Path))
                                   .ToDictionary(FileSystemEntry => FileSystemEntry.Name)
            ;
            var FilesToRemove    = new LinkedList <FileSystemEntry>();
            var FilesToUpdate    = new LinkedList <FileSystemEntry>();
            var FoldersToExplore = new LinkedList <String>();

            // Folders to Explore.
            foreach (var PairSourceFile in SourceFiles)
            {
                CheckCanceling();

                var SourceFile     = PairSourceFile.Value;
                var SourceFileName = PairSourceFile.Key;

                if (SourceFile.Type == FileSystemEntry.EntryType.Directory)
                {
                    FoldersToExplore.AddLast(FileSystem.CombinePath(Path, SourceFileName));
                }
            }

            foreach (var PairSourceFile in SourceFiles)
            {
                CheckCanceling();

                var SourceFile     = PairSourceFile.Value;
                var SourceFileName = PairSourceFile.Key;

                // New file (No contained in the Destination).
                if (!DestinationFiles.ContainsKey(SourceFileName))
                {
                    // Add New Files.
                    if (_SynchronizationMode.HasFlag(SynchronizationMode.CopyNewFiles))
                    {
                        FilesToUpdate.AddLast(SourceFile);
                    }
                }
                // Existant file (Contained in the Destination)
                else
                {
                    FileSystemEntry DestinationFile = DestinationFiles[SourceFileName];

                    bool AreEquals = !SourceFile.SpecialFlags.HasFlag(FileSystemEntry.SpecialFlagsTypes.SynchronizeAlways);

                    // Check old files for updated.
                    if (_SynchronizationMode.HasFlag(SynchronizationMode.UpdateOldFiles))
                    {
                        if (_ReferenceMode.HasFlag(ReferenceMode.Size) && (SourceFile.Size != DestinationFile.Size))
                        {
                            AreEquals = false;
                        }

                        if (_ReferenceMode.HasFlag(ReferenceMode.LastWriteTime) && (SourceFile.Time.LastWriteTime != DestinationFile.Time.LastWriteTime))
                        {
                            //Console.WriteLine(SourceFile + ":  " + SourceFile.Time.LastWriteTime + " != " + DestinationFile.Time.LastWriteTime);
                            AreEquals = false;
                        }
                    }

                    if (!AreEquals)
                    {
                        FilesToUpdate.AddLast(SourceFile);
                    }
                }
            }

            // Delete Old Files.
            if (_SynchronizationMode.HasFlag(SynchronizationMode.DeleteOldFiles))
            {
                throw (new NotImplementedException());

                /*
                 * foreach (var PairDestinationFile in DestinationFiles)
                 * {
                 *      CheckCanceling();
                 *
                 *      var DestinationFile = PairDestinationFile.Value;
                 *      var DestinationFileName = PairDestinationFile.Key;
                 *
                 *      // File was deleted (No contained in the Source).
                 *      if (!SourceFiles.ContainsKey(DestinationFileName))
                 *      {
                 *              FilesToRemove.AddLast(DestinationFile);
                 *      }
                 * }
                 */
            }

            int step  = 0;
            int steps = FilesToUpdate.Count + FilesToRemove.Count + FoldersToExplore.Count;

            foreach (var FileToUpdate in FilesToUpdate)
            {
                String FileToUpdatePathFileName = FileSystem.CombinePath(Path, FileToUpdate.Name);

                CheckCanceling();
                CallStep(GetStep(StepFrom, StepTo, step++, steps), String.Format(UpdatingFormat, FileToUpdatePathFileName));

                if (FileToUpdate.Type == FileSystemEntry.EntryType.Directory)
                {
                    Console.WriteLine("Directory: " + FileToUpdatePathFileName);
                    CreateFolder(FileToUpdatePathFileName);
                }
                else
                {
                    CopyFile(FileToUpdatePathFileName);
                }
            }


            foreach (var FileToRemove in FilesToRemove)
            {
                String FileToRemovePathFileName = FileSystem.CombinePath(Path, FileToRemove.Name);

                CheckCanceling();
                CallStep(GetStep(StepFrom, StepTo, step++, steps), String.Format(RemovingFormat, FileToRemovePathFileName));

                RemoveFile(FileToRemovePathFileName);
            }

            foreach (var FolderName in FoldersToExplore)
            {
                CheckCanceling();

                _SynchronizeFolder(
                    FolderName,
                    GetStep(StepFrom, StepTo, step + 0, steps),
                    GetStep(StepFrom, StepTo, step + 1, steps)
                    );

                step++;
            }
        }