public async Task <VirtualFile> CopyFile(VirtualFile file, VirtualDirectory targetDirectory, Action <ProgressArgs> progressCallback, CancellationToken cancellationToken)
        {
            var fileEntry = getFileEntry(file);
            var filename  = VirtualPath.GetFileName(file.Name);//get filename from full path

            if (fileEntry.DirectoryId == targetDirectory.Id)
            {
                filename = $"Copy {filename}";
            }

            var idx = 0;

            while (targetDirectory.GetFiles(false, filename).Any())
            {
                var name = VirtualPath.GetFileNameWithoutExtension(filename);
                var ext  = VirtualPath.GetFileExtension(filename);
                filename = $"{name} ({++idx}).{ext}";
            }

            var createdFile = targetDirectory.CreateFile(filename);

            using (var newFileStream = createdFile.Open(FileMode.Open, FileAccess.Write))
                using (var sourceFileStream = file.Open(FileMode.Open, FileAccess.Read))
                {
                    newFileStream.SetLength(sourceFileStream.Length);
                    var restBytes       = sourceFileStream.Length;
                    var buffer          = BufferHelper.GetBuffer(sourceFileStream);
                    var currentProgress = -1;
                    while (restBytes > 0 && !cancellationToken.IsCancellationRequested)
                    {
                        try
                        {
                            var count = (int)(restBytes > buffer.Length ? buffer.Length : restBytes);
                            var read  = await sourceFileStream.ReadAsync(buffer, 0, count, cancellationToken);

                            await newFileStream.WriteAsync(buffer, 0, count, cancellationToken);

                            restBytes -= read;
                        }
                        catch (TaskCanceledException)
                        {
                        }

                        //report progress
                        var progress = sourceFileStream.GetProgress();
                        if (progress == currentProgress)
                        {
                            continue;
                        }

                        currentProgress = progress;
                        var message      = VirtualPath.GetFileName(createdFile.Name);
                        var progressArgs = new CopyProgressArgs(progress, message)
                        {
                            Operation = Operation.Copying
                        };
                        _synchronizationContext.Post(x => progressCallback?.Invoke((ProgressArgs)x), progressArgs);
                    }
                }

            if (!cancellationToken.IsCancellationRequested)
            {
                return(createdFile);
            }

            Remove(createdFile);
            _directoryWatcherSource.RaiseDeleted(targetDirectory, file);

            return(createdFile);
        }