public async Task <IHttpActionResult> DownloadCourseModuleClip(string clipname, ClipToSave clipToSave)
        {
            ClipDownloadData clipUrl = null;

            // 1- get the video clip url to download.
            try
            {
                clipUrl = GetClipUrl(clipToSave);

                // 2- make sure the folders structure exist.
                var videoSaveDirectory = SetUpVideoFolderStructure(clipToSave.CourseTitle, clipToSave.ModuleTitle, clipToSave);

                // 2b- create course information, if missing
                SaveCourseInformation(clipToSave);

                // 3- download the video and report progress back.
                int  receivedBytes     = 0;
                long totalBytes        = 0;
                var  videoFileName     = ((clipToSave.ClipIndex + 1).ToString("D2") + " - " + clipToSave.Title + ".mp4").ToValidFileName();
                var  videoSaveLocation = videoSaveDirectory.FullName + "\\raw-" + videoFileName;

                using (var client = new WebClient())
                    using (var regStream = await client.OpenReadTaskAsync(clipUrl.URLs[0].URL))
                        using (var stream = new ThrottledStream(regStream, 115200))
                        {
                            byte[] buffer = new byte[1024];
                            totalBytes = Int32.Parse(client.ResponseHeaders[HttpResponseHeader.ContentLength]);
                            stream.MaximumBytesPerSecond = GetClipMaxDownloadSpeed(clipToSave.DurationSeconds, totalBytes);

                            using (var fileStream = File.OpenWrite(videoSaveLocation))
                            {
                                for (;;)
                                {
                                    int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);

                                    if (bytesRead == 0)
                                    {
                                        await Task.Yield();

                                        break;
                                    }

                                    receivedBytes += bytesRead;
                                    var progress = new ProgressArgs()
                                    {
                                        Id            = clipToSave.Name,
                                        BytesReceived = receivedBytes,
                                        FileName      = videoFileName,
                                        TotalBytes    = totalBytes,
                                        IsDownloading = true,
                                        Extra         = new { clipToSave.ModuleIndex, clipToSave.ClipIndex }
                                    };
                                    fileStream.Write(buffer, 0, bytesRead);
                                    var hubContext = GlobalHost.ConnectionManager.GetHubContext <ProgressHub>();
                                    hubContext.Clients.All.updateProgress(progress);
                                }
                            }
                        }

                // 4- save the video file.
                var inputFile = new MediaFile {
                    Filename = videoSaveLocation
                };
                var outputFile = new MediaFile {
                    Filename = videoSaveDirectory.FullName + "\\" + videoFileName
                };

                if (File.Exists(outputFile.Filename))
                {
                    File.Delete(outputFile.Filename);
                }
                File.Move(inputFile.Filename, outputFile.Filename);

                // 5- Create srt files
                if (Constants.SUBTITLES)
                {
                    var srtFilename = outputFile.Filename.Substring(0, outputFile.Filename.Length - 4) + ".srt";
                    var srtString   = clipToSave.TranscriptClip.GetSrtString(clipToSave.DurationSeconds);
                    if (srtString.Length > 4)
                    {
                        File.WriteAllText(srtFilename, srtString);
                        HandleEmbeddedSubtitles(outputFile.Filename, srtFilename);
                    }
                }

                return(Ok(new ProgressArgs()
                {
                    Id = clipToSave.Name,
                    BytesReceived = receivedBytes,
                    FileName = videoFileName,
                    TotalBytes = totalBytes,
                    IsDownloading = false,
                    Extra = new { clipToSave.ModuleIndex, clipToSave.ClipIndex }
                }));
            }
            catch (Exception exception)
            {
                return(HandleException(exception));
            }
        }
        private async void SaveCourseInformation(CourseSimpleClip clip)
        {
            String courseName = clip.ID.Substring(0, clip.ID.IndexOf("|"));
            Course course     = null;

            courses.TryGetValue(courseName, out course);
            if (course == null)
            {
                return;
            }
            var descriptionFile = GetBaseFolderStructure(course.Title) + "\\description.txt";
            var levelFile       = GetBaseFolderStructure(course.Title) + "\\level.txt";
            var authorsFile     = GetBaseFolderStructure(course.Title) + "\\authors.txt";
            var dateFile        = GetBaseFolderStructure(course.Title) + "\\date.txt";
            var excerciceFile   = GetBaseFolderStructure(course.Title) + "\\" + course.Title.ToValidFileName() + "-excercice.zip";

            if (!File.Exists(descriptionFile))
            {
                File.WriteAllText(descriptionFile, course.Description);
            }
            if (!File.Exists(levelFile))
            {
                File.WriteAllText(levelFile, course.Level);
            }
            if (!File.Exists(dateFile))
            {
                File.WriteAllText(dateFile, DateTime.Parse(course.ReleaseDate).ToString("dd/MM/yyyy"));
            }
            if (!File.Exists(authorsFile))
            {
                String separator = "";
                String authors   = "";
                foreach (Author author in course.Authors)
                {
                    authors   = separator + author.FirstName + " " + author.LastName;
                    separator = ", ";
                }
                File.WriteAllText(authorsFile, String.Join(", ", authors));
            }
            if (!File.Exists(excerciceFile))
            {
                if (course.ExerciseFiles != null)
                {
                    try
                    {
                        using (var client = new WebClient())
                            using (var regStream = await client.OpenReadTaskAsync(course.ExerciseFiles.exerciseFilesUrl))
                                using (var stream = new ThrottledStream(regStream, 115200))
                                {
                                    byte[] buffer = new byte[1024];

                                    using (var fileStream = File.OpenWrite(excerciceFile))
                                    {
                                        for (;;)
                                        {
                                            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);

                                            if (bytesRead == 0)
                                            {
                                                await Task.Yield();

                                                break;
                                            }

                                            fileStream.Write(buffer, 0, bytesRead);
                                        }
                                    }
                                }
                    } catch
                    {
                    }
                }
            }
        }
        public async Task<IHttpActionResult> DownloadCourseModuleClip(string clipname, ClipToSave clipToSave)
        {
            string clipUrl = string.Empty;
            // 1- get the video clip url to download.
            try
            {
                clipUrl = GetClipUrl(clipToSave);

                // 2- make sure the folders structure exist.
                var videoSaveDirectory = SetUpVideoFolderStructure(clipToSave.CourseTitle,
                    (clipToSave.ModuleIndex + 1).ToString("D2") + " - " + clipToSave.ModuleTitle,
                    (clipToSave.ClipIndex + 1).ToString("D2") + " - " + clipToSave.Title);

                // 3- download the video and report progress back.
                int receivedBytes = 0;
                long totalBytes = 0;
                var videoFileName = ((clipToSave.ClipIndex + 1).ToString("D2") + " - " + clipToSave.Title + ".mp4").ToValidFileName();
                var videoSaveLocation = videoSaveDirectory.FullName + "\\raw-" + videoFileName;

                using (var client = new WebClient())
                using (var regStream = await client.OpenReadTaskAsync(clipUrl))
                using (var stream = new ThrottledStream(regStream, 115200))
                {
                    byte[] buffer = new byte[1024];
                    totalBytes = Int32.Parse(client.ResponseHeaders[HttpResponseHeader.ContentLength]);
                    stream.MaximumBytesPerSecond = GetClipMaxDownloadSpeed(clipToSave.DurationSeconds, totalBytes);

                    using (var fileStream = File.OpenWrite(videoSaveLocation))
                    {
                        for (;;)
                        {
                            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                            if (bytesRead == 0)
                            {
                                await Task.Yield();
                                break;
                            }

                            receivedBytes += bytesRead;
                            var progress = new ProgressArgs()
                            {
                                Id = clipToSave.Name,
                                BytesReceived = receivedBytes,
                                FileName = videoFileName,
                                TotalBytes = totalBytes,
                                IsDownloading = true,
                                Extra = new { clipToSave.ModuleIndex, clipToSave.ClipIndex }
                            };
                            fileStream.Write(buffer, 0, bytesRead);
                            var hubContext = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
                            hubContext.Clients.All.updateProgress(progress);
                        }
                    }
                }

                // 4- save the video file.
                var inputFile = new MediaFile { Filename = videoSaveDirectory.FullName + "\\raw-" + videoFileName };
                var outputFile = new MediaFile { Filename = videoSaveDirectory.FullName + "\\" + videoFileName };

                File.Move(inputFile.Filename, outputFile.Filename);

                // 5- Create srt files
                if (Constants.SUBTITLES)
                {
                    var srtFilename = outputFile.Filename.Substring(0, outputFile.Filename.Length - 4) + ".srt";
                    var srtString = clipToSave.TranscriptClip.GetSrtString(clipToSave.DurationSeconds);
                    File.WriteAllText(srtFilename, srtString);
                }

                return Ok(new ProgressArgs()
                {
                    Id = clipToSave.Name,
                    BytesReceived = receivedBytes,
                    FileName = videoFileName,
                    TotalBytes = totalBytes,
                    IsDownloading = false,
                    Extra = new { clipToSave.ModuleIndex, clipToSave.ClipIndex }
                });
            }
            catch (Exception exception)
            {
                return HandleException(exception);
            }
        }