From 500e9af6c3cf27ca5cc0fedb508f4bcb6d11fff1 Mon Sep 17 00:00:00 2001
From: "kay.one" <kay.one@gmail.com>
Date: Mon, 23 May 2011 21:12:54 -0700
Subject: [PATCH] Fixed a bug where reports weren't being added to history

---
 NzbDrone.Core.Test/DownloadProviderTest.cs    |  55 ++++++
 NzbDrone.Core.Test/EpisodeProviderTest.cs     | Bin 5794 -> 5800 bytes
 NzbDrone.Core.Test/IndexerProviderTest.cs     |  17 +-
 NzbDrone.Core.Test/InventoryProviderTest.cs   | 161 +++++++++++++-----
 NzbDrone.Core.Test/JobProviderTest.cs         |  30 ++--
 NzbDrone.Core.Test/MediaFileProviderTests.cs  |   2 +-
 NzbDrone.Core.Test/NzbDrone.Core.Test.csproj  |   1 +
 NzbDrone.Core.Test/ParserTest.cs              |  18 +-
 NzbDrone.Core.Test/SabProviderTest.cs         |   2 +-
 NzbDrone.Core/Model/EpisodeParseResult.cs     |  12 +-
 NzbDrone.Core/Parser.cs                       |   4 +-
 NzbDrone.Core/Providers/DownloadProvider.cs   |  26 ++-
 .../Providers/Indexer/IndexerBase.cs          |   2 +
 .../Providers/Indexer/InventoryProvider.cs    |  59 ++++---
 NzbDrone.Core/Providers/MediaFileProvider.cs  |   4 +-
 NzbDrone.Core/Providers/SabProvider.cs        |   4 +-
 NzbDrone.Web/Controllers/SeriesController.cs  |  85 +--------
 NzbDrone.Web/Views/Series/Details.cshtml      |  87 +++++-----
 18 files changed, 344 insertions(+), 225 deletions(-)
 create mode 100644 NzbDrone.Core.Test/DownloadProviderTest.cs

diff --git a/NzbDrone.Core.Test/DownloadProviderTest.cs b/NzbDrone.Core.Test/DownloadProviderTest.cs
new file mode 100644
index 000000000..db2c8758f
--- /dev/null
+++ b/NzbDrone.Core.Test/DownloadProviderTest.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using AutoMoq;
+using FizzWare.NBuilder;
+using Gallio.Framework;
+using MbUnit.Framework;
+using MbUnit.Framework.ContractVerifiers;
+using Moq;
+using NzbDrone.Core.Model;
+using NzbDrone.Core.Providers;
+using NzbDrone.Core.Repository;
+
+// ReSharper disable InconsistentNaming
+namespace NzbDrone.Core.Test
+{
+    [TestFixture]
+    public class DownloadProviderTest
+    {
+        [Test]
+        public void Download_report_should_send_to_sab_and_add_to_history()
+        {
+            var mocker = new AutoMoqer(MockBehavior.Strict);
+            var parseResult = Builder<EpisodeParseResult>.CreateNew()
+                .With(e => e.Episodes = Builder<Episode>.CreateListOfSize(2)
+                    .WhereTheFirst(1).Has(s => s.EpisodeId = 12)
+                    .AndTheNext(1).Has(s => s.EpisodeId = 99)
+                    .Build())
+                    .Build();
+
+            const string sabTitle = "My fake sab title";
+            mocker.GetMock<SabProvider>()
+                .Setup(s => s.IsInQueue(It.IsAny<String>()))
+                .Returns(false);
+
+            mocker.GetMock<SabProvider>()
+                .Setup(s => s.AddByUrl(parseResult.NzbUrl, sabTitle))
+                .Returns(true);
+
+            mocker.GetMock<SabProvider>()
+               .Setup(s => s.GetSabTitle(parseResult))
+               .Returns(sabTitle);
+
+            mocker.GetMock<HistoryProvider>()
+                .Setup(s => s.Add(It.Is<History>(h=>h.EpisodeId == 12)));
+            mocker.GetMock<HistoryProvider>()
+    .Setup(s => s.Add(It.Is<History>(h => h.EpisodeId == 99)));
+
+            mocker.Resolve<DownloadProvider>().DownloadReport(parseResult);
+
+            
+            mocker.VerifyAllMocks();
+        }
+    }
+}
diff --git a/NzbDrone.Core.Test/EpisodeProviderTest.cs b/NzbDrone.Core.Test/EpisodeProviderTest.cs
index ca1f04183d2ad398154b3328c0203f5d4445bd98..36816c04c910b0c2a9a9b3f6eb5067a6d5b4466b 100644
GIT binary patch
delta 19
bcmZ3ayFz!v6CO6d(%hufqRmfu_HhCLQQrt2

delta 12
UcmZ3XyGVD#6Q0elc=mAu04A6PwEzGB

diff --git a/NzbDrone.Core.Test/IndexerProviderTest.cs b/NzbDrone.Core.Test/IndexerProviderTest.cs
index 1eb820f59..b0ac3cae6 100644
--- a/NzbDrone.Core.Test/IndexerProviderTest.cs
+++ b/NzbDrone.Core.Test/IndexerProviderTest.cs
@@ -41,7 +41,8 @@ namespace NzbDrone.Core.Test
                 .Setup(c => c.GetSettings(It.IsAny<Type>()))
                 .Returns(fakeSettings);
 
-            var parseResults = mocker.Resolve<MockIndexer>().Fetch();
+            var mockIndexer = mocker.Resolve<MockIndexer>();
+            var parseResults = mockIndexer.Fetch();
 
             foreach (var episodeParseResult in parseResults)
             {
@@ -51,6 +52,11 @@ namespace NzbDrone.Core.Test
 
 
             Assert.IsNotEmpty(parseResults);
+
+            Assert.ForAll(parseResults, s => Assert.AreEqual(mockIndexer.Name, s.Indexer));
+            Assert.ForAll(parseResults, s => Assert.AreNotEqual("", s.NzbTitle));
+            Assert.ForAll(parseResults, s => Assert.AreNotEqual(null, s.NzbTitle));
+
             ExceptionVerification.ExcpectedWarns(warns);
         }
 
@@ -70,7 +76,8 @@ namespace NzbDrone.Core.Test
                 .Setup(c => c.GetSettings(It.IsAny<Type>()))
                 .Returns(fakeSettings);
 
-            var parseResults = mocker.Resolve<Newzbin>().Fetch();
+            var newzbinProvider = mocker.Resolve<Newzbin>();
+            var parseResults = newzbinProvider.Fetch();
 
             foreach (var episodeParseResult in parseResults)
             {
@@ -80,6 +87,10 @@ namespace NzbDrone.Core.Test
 
 
             Assert.IsNotEmpty(parseResults);
+            Assert.ForAll(parseResults, s => Assert.AreEqual(newzbinProvider.Name, s.Indexer));
+            Assert.ForAll(parseResults, s => Assert.AreNotEqual("", s.NzbTitle));
+            Assert.ForAll(parseResults, s => Assert.AreNotEqual(null, s.NzbTitle));
+
             ExceptionVerification.ExcpectedWarns(1);
         }
 
@@ -111,7 +122,7 @@ namespace NzbDrone.Core.Test
             Assert.IsNotNull(result);
             Assert.AreEqual(summary, result.EpisodeTitle);
             Assert.AreEqual(season, result.SeasonNumber);
-            Assert.AreEqual(episode, result.Episodes[0]);
+            Assert.AreEqual(episode, result.EpisodeNumbers[0]);
             Assert.AreEqual(quality, result.Quality);
         }
 
diff --git a/NzbDrone.Core.Test/InventoryProviderTest.cs b/NzbDrone.Core.Test/InventoryProviderTest.cs
index bbf0113c6..0e6043f9c 100644
--- a/NzbDrone.Core.Test/InventoryProviderTest.cs
+++ b/NzbDrone.Core.Test/InventoryProviderTest.cs
@@ -23,37 +23,56 @@ namespace NzbDrone.Core.Test
     // ReSharper disable InconsistentNaming
     public class InventoryProviderTest : TestBase
     {
-        private EpisodeParseResult parseResult;
+        private EpisodeParseResult parseResultMulti;
         private Series series;
         private Episode episode;
+        private Episode episode2;
+        private EpisodeParseResult parseResultSingle;
 
         [SetUp]
         public new void Setup()
         {
-            parseResult = new EpisodeParseResult()
+            parseResultMulti = new EpisodeParseResult()
                                {
                                    CleanTitle = "Title",
                                    EpisodeTitle = "EpisodeTitle",
                                    Language = LanguageType.English,
                                    Proper = true,
                                    Quality = QualityTypes.Bluray720,
-                                   Episodes = new List<int> { 3 },
+                                   EpisodeNumbers = new List<int> { 3, 4 },
                                    SeasonNumber = 12,
                                    AirDate = DateTime.Now.AddDays(-12).Date
-
                                };
 
+            parseResultSingle = new EpisodeParseResult()
+            {
+                CleanTitle = "Title",
+                EpisodeTitle = "EpisodeTitle",
+                Language = LanguageType.English,
+                Proper = true,
+                Quality = QualityTypes.Bluray720,
+                EpisodeNumbers = new List<int> { 3 },
+                SeasonNumber = 12,
+                AirDate = DateTime.Now.AddDays(-12).Date
+            };
+
             series = Builder<Series>.CreateNew()
                 .With(c => c.Monitored = true)
-                .With(d => d.CleanTitle = parseResult.CleanTitle)
+                .With(d => d.CleanTitle = parseResultMulti.CleanTitle)
                 .Build();
 
             episode = Builder<Episode>.CreateNew()
-                .With(c => c.EpisodeNumber = parseResult.Episodes[0])
-                .With(c => c.SeasonNumber = parseResult.SeasonNumber)
-                .With(c => c.AirDate = parseResult.AirDate)
+                .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[0])
+                .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber)
+                .With(c => c.AirDate = parseResultMulti.AirDate)
                 .Build();
 
+            episode2 = Builder<Episode>.CreateNew()
+             .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[1])
+             .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber)
+             .With(c => c.AirDate = parseResultMulti.AirDate)
+             .Build();
+
             base.Setup();
 
         }
@@ -71,7 +90,7 @@ namespace NzbDrone.Core.Test
                 .Returns(series);
 
             //Act
-            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResult);
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultMulti);
 
             //Assert
             Assert.IsFalse(result);
@@ -90,7 +109,7 @@ namespace NzbDrone.Core.Test
                 .Returns<Series>(null);
 
             //Act
-            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResult);
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultMulti);
 
             //Assert
             Assert.IsFalse(result);
@@ -107,12 +126,12 @@ namespace NzbDrone.Core.Test
                 .Returns(series);
 
             mocker.GetMock<SeriesProvider>()
-               .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality))
+               .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality))
                .Returns(false);
 
 
             //Act
-            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResult);
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultMulti);
 
             //Assert
             Assert.IsFalse(result);
@@ -131,15 +150,15 @@ namespace NzbDrone.Core.Test
                 .Returns(series);
 
             mocker.GetMock<SeriesProvider>()
-               .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality))
+               .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality))
                .Returns(true);
 
             mocker.GetMock<SeasonProvider>()
-                .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
+                .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber))
                 .Returns(true);
 
             //Act
-            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResult);
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultMulti);
 
             //Assert
             Assert.IsFalse(result);
@@ -163,21 +182,29 @@ namespace NzbDrone.Core.Test
                 .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber))
                 .Returns(episode);
 
+            mocker.GetMock<EpisodeProvider>()
+                .Setup(p => p.GetEpisode(episode2.SeriesId, episode2.SeasonNumber, episode2.EpisodeNumber))
+                .Returns(episode2);
+
 
             mocker.GetMock<SeriesProvider>()
-               .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality))
+               .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality))
                .Returns(true);
 
             mocker.GetMock<SeasonProvider>()
-                .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
+                .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber))
+                .Returns(false);
+
+            mocker.GetMock<EpisodeProvider>()
+                .Setup(p => p.IsNeeded(parseResultMulti, episode))
                 .Returns(false);
 
             mocker.GetMock<EpisodeProvider>()
-                .Setup(p => p.IsNeeded(parseResult, episode))
+                .Setup(p => p.IsNeeded(parseResultMulti, episode2))
                 .Returns(false);
 
             //Act
-            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResult);
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultMulti);
 
             //Assert
             Assert.IsFalse(result);
@@ -198,25 +225,24 @@ namespace NzbDrone.Core.Test
                 .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber))
                 .Returns(episode);
 
-
             mocker.GetMock<SeriesProvider>()
-               .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality))
+               .Setup(p => p.QualityWanted(series.SeriesId, parseResultSingle.Quality))
                .Returns(true);
 
             mocker.GetMock<SeasonProvider>()
-                .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
+                .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber))
                 .Returns(false);
 
             mocker.GetMock<EpisodeProvider>()
-                .Setup(p => p.IsNeeded(parseResult, episode))
+                .Setup(p => p.IsNeeded(parseResultSingle, episode))
                 .Returns(true);
 
             mocker.GetMock<HistoryProvider>()
-                .Setup(p => p.Exists(episode.EpisodeId, parseResult.Quality, parseResult.Proper))
+                .Setup(p => p.Exists(episode.EpisodeId, parseResultSingle.Quality, parseResultSingle.Proper))
                 .Returns(true);
 
             //Act
-            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResult);
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultSingle);
 
             //Assert
             Assert.IsFalse(result);
@@ -242,19 +268,19 @@ namespace NzbDrone.Core.Test
 
 
             mocker.GetMock<SeriesProvider>()
-               .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality))
+               .Setup(p => p.QualityWanted(series.SeriesId, parseResultSingle.Quality))
                .Returns(true);
 
             mocker.GetMock<SeasonProvider>()
-                .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
+                .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber))
                 .Returns(false);
 
             mocker.GetMock<EpisodeProvider>()
-                .Setup(p => p.IsNeeded(parseResult, episode))
+                .Setup(p => p.IsNeeded(parseResultSingle, episode))
                 .Returns(false);
 
             //Act
-            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResult);
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultSingle);
 
             //Assert
             Assert.IsFalse(result);
@@ -272,11 +298,11 @@ namespace NzbDrone.Core.Test
                 .Returns(series);
 
             mocker.GetMock<SeriesProvider>()
-               .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality))
+               .Setup(p => p.QualityWanted(series.SeriesId, parseResultSingle.Quality))
                .Returns(true);
 
             mocker.GetMock<SeasonProvider>()
-                .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
+                .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber))
                 .Returns(false);
 
             mocker.GetMock<EpisodeProvider>()
@@ -292,11 +318,11 @@ namespace NzbDrone.Core.Test
                .Returns(12);
 
             mocker.GetMock<EpisodeProvider>()
-                .Setup(p => p.IsNeeded(parseResult, It.IsAny<Episode>()))
+                .Setup(p => p.IsNeeded(parseResultSingle, It.IsAny<Episode>()))
                 .Returns(false);
 
             //Act
-            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResult);
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultSingle);
 
             //Assert
             Assert.IsFalse(result);
@@ -305,7 +331,7 @@ namespace NzbDrone.Core.Test
 
 
         [Test]
-        public void file_needed_should_return_true()
+        public void first_file_needed_should_return_true()
         {
             var mocker = new AutoMoqer(MockBehavior.Strict);
 
@@ -317,30 +343,83 @@ namespace NzbDrone.Core.Test
                 .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber))
                 .Returns(episode);
 
+            mocker.GetMock<EpisodeProvider>()
+             .Setup(p => p.GetEpisode(episode2.SeriesId, episode2.SeasonNumber, episode2.EpisodeNumber))
+             .Returns(episode2);
 
             mocker.GetMock<SeriesProvider>()
-               .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality))
+               .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality))
                .Returns(true);
 
             mocker.GetMock<SeasonProvider>()
-                .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
+                .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber))
+                .Returns(false);
+
+            mocker.GetMock<EpisodeProvider>()
+                .Setup(p => p.IsNeeded(parseResultMulti, episode))
+                .Returns(true);
+
+            mocker.GetMock<HistoryProvider>()
+                .Setup(p => p.Exists(episode.EpisodeId, parseResultMulti.Quality, parseResultMulti.Proper))
+                .Returns(false);
+
+            //Act
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultMulti);
+
+            //Assert
+            Assert.IsTrue(result);
+            Assert.Contains(parseResultMulti.Episodes, episode);
+            Assert.Contains(parseResultMulti.Episodes, episode2);
+            Assert.AreEqual(series, parseResultMulti.Series);
+            mocker.VerifyAllMocks();
+        }
+
+        [Test]
+        public void second_file_needed_should_return_true()
+        {
+            var mocker = new AutoMoqer(MockBehavior.Strict);
+
+            mocker.GetMock<SeriesProvider>()
+                .Setup(p => p.FindSeries(It.IsAny<String>()))
+                .Returns(series);
+
+            mocker.GetMock<EpisodeProvider>()
+                .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber))
+                .Returns(episode);
+
+            mocker.GetMock<EpisodeProvider>()
+                .Setup(p => p.GetEpisode(episode2.SeriesId, episode2.SeasonNumber, episode2.EpisodeNumber))
+                .Returns(episode2);
+
+
+            mocker.GetMock<SeriesProvider>()
+               .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality))
+               .Returns(true);
+
+            mocker.GetMock<SeasonProvider>()
+                .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber))
+                .Returns(false);
+
+            mocker.GetMock<EpisodeProvider>()
+                .Setup(p => p.IsNeeded(parseResultMulti, episode))
                 .Returns(false);
 
             mocker.GetMock<EpisodeProvider>()
-                .Setup(p => p.IsNeeded(parseResult, episode))
+                .Setup(p => p.IsNeeded(parseResultMulti, episode2))
                 .Returns(true);
 
             mocker.GetMock<HistoryProvider>()
-                .Setup(p => p.Exists(episode.EpisodeId, parseResult.Quality, parseResult.Proper))
+                .Setup(p => p.Exists(episode2.EpisodeId, parseResultMulti.Quality, parseResultMulti.Proper))
                 .Returns(false);
 
             //Act
-            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResult);
+            var result = mocker.Resolve<InventoryProvider>().IsNeeded(parseResultMulti);
 
             //Assert
             Assert.IsTrue(result);
-            Assert.IsNotNull(parseResult.Series);
-            Assert.AreEqual(series, parseResult.Series);
+            Assert.Contains(parseResultMulti.Episodes, episode);
+            Assert.Contains(parseResultMulti.Episodes, episode2);
+            Assert.AreEqual(series, parseResultMulti.Series);
             mocker.VerifyAllMocks();
         }
     }
diff --git a/NzbDrone.Core.Test/JobProviderTest.cs b/NzbDrone.Core.Test/JobProviderTest.cs
index f1af906bc..51e585125 100644
--- a/NzbDrone.Core.Test/JobProviderTest.cs
+++ b/NzbDrone.Core.Test/JobProviderTest.cs
@@ -17,7 +17,7 @@ namespace NzbDrone.Core.Test
         [Test]
         public void Run_Jobs_Updates_Last_Execution()
         {
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new FakeJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new FakeJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -39,7 +39,7 @@ namespace NzbDrone.Core.Test
         public void Run_Jobs_Updates_Last_Execution_Mark_as_unsuccesful()
         {
 
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new BrokenJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new BrokenJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test
         //after execution so the job can successfully run.
         public void can_run_job_again()
         {
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new FakeJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new FakeJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -84,7 +84,7 @@ namespace NzbDrone.Core.Test
         //after execution so the job can successfully run.
         public void can_run_async_job_again()
         {
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new FakeJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new FakeJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -106,7 +106,7 @@ namespace NzbDrone.Core.Test
         //after execution so the job can successfully run.
         public void no_concurent_jobs()
         {
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new SlowJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new SlowJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -129,7 +129,7 @@ namespace NzbDrone.Core.Test
         //after execution so the job can successfully run.
         public void can_run_broken_async_job_again()
         {
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new BrokenJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new BrokenJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -152,7 +152,7 @@ namespace NzbDrone.Core.Test
         //after execution so the job can successfully run.
         public void can_run_two_jobs_at_the_same_time()
         {
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new SlowJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new SlowJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -186,7 +186,7 @@ namespace NzbDrone.Core.Test
         {
             var slowJob = new SlowJob();
 
-            IEnumerable<IJob> fakeJobs = new List<IJob> { slowJob };
+            IList<IJob> fakeJobs = new List<IJob> { slowJob };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -214,7 +214,7 @@ namespace NzbDrone.Core.Test
         public void Init_Jobs()
         {
             var fakeTimer = new FakeJob();
-            IEnumerable<IJob> fakeJobs = new List<IJob> { fakeTimer };
+            IList<IJob> fakeJobs = new List<IJob> { fakeTimer };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -245,7 +245,7 @@ namespace NzbDrone.Core.Test
             for (int i = 0; i < 2; i++)
             {
                 var fakeTimer = new FakeJob();
-                IEnumerable<IJob> fakeJobs = new List<IJob> { fakeTimer };
+                IList<IJob> fakeJobs = new List<IJob> { fakeTimer };
                 var mocker = new AutoMoqer();
 
                 mocker.SetConstant(repo);
@@ -276,7 +276,7 @@ namespace NzbDrone.Core.Test
             for (int i = 0; i < 2; i++)
             {
                 var disabledJob = new DisabledJob();
-                IEnumerable<IJob> fakeJobs = new List<IJob> { disabledJob };
+                IList<IJob> fakeJobs = new List<IJob> { disabledJob };
                 var mocker = new AutoMoqer();
 
                 mocker.SetConstant(repo);
@@ -302,7 +302,7 @@ namespace NzbDrone.Core.Test
         [Test]
         public void Get_Next_Execution_Time()
         {
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new FakeJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new FakeJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -327,7 +327,7 @@ namespace NzbDrone.Core.Test
 
 
             var disabledJob = new DisabledJob();
-            IEnumerable<IJob> fakeJobs = new List<IJob> { disabledJob };
+            IList<IJob> fakeJobs = new List<IJob> { disabledJob };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(repo);
@@ -348,7 +348,7 @@ namespace NzbDrone.Core.Test
         [Test]
         public void SingleId_do_not_update_last_execution()
         {
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new FakeJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new FakeJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
@@ -369,7 +369,7 @@ namespace NzbDrone.Core.Test
         [Test]
         public void SingleId_do_not_set_success()
         {
-            IEnumerable<IJob> fakeJobs = new List<IJob> { new FakeJob() };
+            IList<IJob> fakeJobs = new List<IJob> { new FakeJob() };
             var mocker = new AutoMoqer();
 
             mocker.SetConstant(MockLib.GetEmptyRepository());
diff --git a/NzbDrone.Core.Test/MediaFileProviderTests.cs b/NzbDrone.Core.Test/MediaFileProviderTests.cs
index 75ef69a47..8ca8d2ba6 100644
--- a/NzbDrone.Core.Test/MediaFileProviderTests.cs
+++ b/NzbDrone.Core.Test/MediaFileProviderTests.cs
@@ -116,7 +116,7 @@ namespace NzbDrone.Core.Test
 
             //Currently can't verify this since the list of episodes are loaded
             //Dynamically by SubSonic
-            //Assert.AreEqual(fakeEpisode, result.Episodes[0]);
+            //Assert.AreEqual(fakeEpisode, result.EpisodeNumbers[0]);
 
             Assert.AreEqual(fakeEpisode.SeriesId, result.SeriesId);
             Assert.AreEqual(QualityTypes.HDTV, result.Quality);
diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index 64bf6f0b3..523d14b39 100644
--- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
+++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
@@ -85,6 +85,7 @@
     </Reference>
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="DownloadProviderTest.cs" />
     <Compile Include="EpisodeStatusTest.cs" />
     <Compile Include="ImportNewSeriesJobTest.cs" />
     <Compile Include="DiskScanJobTest.cs" />
diff --git a/NzbDrone.Core.Test/ParserTest.cs b/NzbDrone.Core.Test/ParserTest.cs
index f113a5584..cd8c2bf64 100644
--- a/NzbDrone.Core.Test/ParserTest.cs
+++ b/NzbDrone.Core.Test/ParserTest.cs
@@ -46,9 +46,9 @@ namespace NzbDrone.Core.Test
         {
             var result = Parser.ParseEpisodeInfo(postTitle);
             Assert.AreEqual(season, result.SeasonNumber);
-            Assert.AreEqual(episode, result.Episodes[0]);
+            Assert.AreEqual(episode, result.EpisodeNumbers[0]);
             Assert.AreEqual(Parser.NormalizeTitle(title), result.CleanTitle);
-            Assert.AreEqual(1, result.Episodes.Count);
+            Assert.AreEqual(1, result.EpisodeNumbers.Count);
         }
 
         [Test]
@@ -60,9 +60,9 @@ namespace NzbDrone.Core.Test
         public void file_path_parse(string path, int season, int episode)
         {
             var result = Parser.ParseEpisodeInfo(path);
-            Assert.Count(1, result.Episodes);
+            Assert.Count(1, result.EpisodeNumbers);
             Assert.AreEqual(season, result.SeasonNumber);
-            Assert.AreEqual(episode, result.Episodes[0]);
+            Assert.AreEqual(episode, result.EpisodeNumbers[0]);
         }
 
 
@@ -110,10 +110,10 @@ namespace NzbDrone.Core.Test
         {
             var result = Parser.ParseEpisodeInfo(postTitle);
             Assert.AreEqual(season, result.SeasonNumber);
-            Assert.Count(episodes.Length, result.Episodes);
-            Assert.AreElementsEqualIgnoringOrder(episodes, result.Episodes);
+            Assert.Count(episodes.Length, result.EpisodeNumbers);
+            Assert.AreElementsEqualIgnoringOrder(episodes, result.EpisodeNumbers);
             Assert.AreEqual(Parser.NormalizeTitle(title), result.CleanTitle);
-            Assert.AreEqual(count, result.Episodes.Count);
+            Assert.AreEqual(count, result.EpisodeNumbers.Count);
         }
 
         [Test]
@@ -129,7 +129,7 @@ namespace NzbDrone.Core.Test
             var airDate = new DateTime(year, month, day);
             Assert.AreEqual(Parser.NormalizeTitle(title), result.CleanTitle);
             Assert.AreEqual(airDate, result.AirDate);
-            Assert.IsNull(result.Episodes);
+            Assert.IsNull(result.EpisodeNumbers);
         }
 
 
@@ -142,7 +142,7 @@ namespace NzbDrone.Core.Test
             var result = Parser.ParseEpisodeInfo(postTitle);
             Assert.AreEqual(season, result.SeasonNumber);
             Assert.AreEqual(Parser.NormalizeTitle(title), result.CleanTitle);
-            Assert.AreEqual(0, result.Episodes.Count);
+            Assert.AreEqual(0, result.EpisodeNumbers.Count);
         }
 
         [Test]
diff --git a/NzbDrone.Core.Test/SabProviderTest.cs b/NzbDrone.Core.Test/SabProviderTest.cs
index d48df6fe0..d5323f6a9 100644
--- a/NzbDrone.Core.Test/SabProviderTest.cs
+++ b/NzbDrone.Core.Test/SabProviderTest.cs
@@ -229,7 +229,7 @@ namespace NzbDrone.Core.Test
             var parsResult = new EpisodeParseResult()
             {
                 AirDate = DateTime.Now,
-                Episodes = episodes.ToList(),
+                EpisodeNumbers = episodes.ToList(),
                 Proper = proper,
                 Quality = quality,
                 SeasonNumber = seasons,
diff --git a/NzbDrone.Core/Model/EpisodeParseResult.cs b/NzbDrone.Core/Model/EpisodeParseResult.cs
index d5892dc9d..4452d8fa9 100644
--- a/NzbDrone.Core/Model/EpisodeParseResult.cs
+++ b/NzbDrone.Core/Model/EpisodeParseResult.cs
@@ -11,7 +11,7 @@ namespace NzbDrone.Core.Model
 
         internal int SeasonNumber { get; set; }
 
-        internal List<int> Episodes { get; set; }
+        internal List<int> EpisodeNumbers { get; set; }
 
         internal string EpisodeTitle { get; set; }
 
@@ -25,15 +25,21 @@ namespace NzbDrone.Core.Model
 
         public string NzbUrl { get; set; }
 
+        public string NzbTitle { get; set; }
+
         public Series Series { get; set; }
 
+        public IList<Episode> Episodes { get; set; }
+
+        public String Indexer { get; set; }
+
         public override string ToString()
         {
-            if (Episodes == null)
+            if (EpisodeNumbers == null)
                 return string.Format("{0} - {1}", CleanTitle, AirDate.Date);
 
             return string.Format("{0} - S{1:00}E{2}", CleanTitle, SeasonNumber,
-                                 String.Join("-", Episodes));
+                                 String.Join("-", EpisodeNumbers));
 
         }
     }
diff --git a/NzbDrone.Core/Parser.cs b/NzbDrone.Core/Parser.cs
index a2a3aef68..91b4e7a82 100644
--- a/NzbDrone.Core/Parser.cs
+++ b/NzbDrone.Core/Parser.cs
@@ -68,7 +68,7 @@ namespace NzbDrone.Core
                             Proper = title.ToLower().Contains("proper"),
                             CleanTitle = seriesName,
                             SeasonNumber = season,
-                            Episodes = new List<int>()
+                            EpisodeNumbers = new List<int>()
                         };
 
                         foreach (Match matchGroup in match)
@@ -83,7 +83,7 @@ namespace NzbDrone.Core
 
                                 for (int i = first; i <= last; i++)
                                 {
-                                    parsedEpisode.Episodes.Add(i);
+                                    parsedEpisode.EpisodeNumbers.Add(i);
                                 }
                             }
                         }
diff --git a/NzbDrone.Core/Providers/DownloadProvider.cs b/NzbDrone.Core/Providers/DownloadProvider.cs
index f249b1c1e..1070eaded 100644
--- a/NzbDrone.Core/Providers/DownloadProvider.cs
+++ b/NzbDrone.Core/Providers/DownloadProvider.cs
@@ -13,11 +13,15 @@ namespace NzbDrone.Core.Providers
     public class DownloadProvider
     {
         private readonly SabProvider _sabProvider;
+        private readonly HistoryProvider _historyProvider;
+        private readonly EpisodeProvider _episodeProvider;
         private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
 
-        public DownloadProvider(SabProvider sabProvider)
+        public DownloadProvider(SabProvider sabProvider, HistoryProvider historyProvider, EpisodeProvider episodeProvider)
         {
             _sabProvider = sabProvider;
+            _historyProvider = historyProvider;
+            _episodeProvider = episodeProvider;
         }
 
         public DownloadProvider()
@@ -34,7 +38,25 @@ namespace NzbDrone.Core.Providers
                 return false;
             }
 
-            return _sabProvider.AddByUrl(parseResult.NzbUrl, sabTitle);
+            var addSuccess = _sabProvider.AddByUrl(parseResult.NzbUrl, sabTitle);
+
+            if (addSuccess)
+            {
+                foreach (var episode in parseResult.Episodes)
+                {
+                    var history = new History();
+                    history.Date = DateTime.Now;
+                    history.Indexer = parseResult.Indexer;
+                    history.IsProper = parseResult.Proper;
+                    history.Quality = parseResult.Quality;
+                    history.NzbTitle = parseResult.NzbTitle;
+                    history.EpisodeId = episode.EpisodeId;
+
+                    _historyProvider.Add(history);
+                }
+            }
+
+            return addSuccess;
         }
     }
 }
\ No newline at end of file
diff --git a/NzbDrone.Core/Providers/Indexer/IndexerBase.cs b/NzbDrone.Core/Providers/Indexer/IndexerBase.cs
index 6e197b6c7..aeee9d96e 100644
--- a/NzbDrone.Core/Providers/Indexer/IndexerBase.cs
+++ b/NzbDrone.Core/Providers/Indexer/IndexerBase.cs
@@ -77,6 +77,8 @@ namespace NzbDrone.Core.Providers.Indexer
                             if (parsedEpisode != null)
                             {
                                 parsedEpisode.NzbUrl = NzbDownloadUrl(item);
+                                parsedEpisode.Indexer = Name;
+                                parsedEpisode.NzbTitle = item.Title.Text;
                                 result.Add(parsedEpisode);
                             }
                         }
diff --git a/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs b/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs
index 70e462a68..363a3332a 100644
--- a/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs
+++ b/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.IO;
 using NLog;
 using NzbDrone.Core.Model;
@@ -36,32 +37,28 @@ namespace NzbDrone.Core.Providers.Indexer
             }
 
             parseResult.Series = series;
+            parseResult.Episodes = new List<Episode>();
 
-            foreach (var episodeNumber in parseResult.Episodes)
+            if (!series.Monitored)
             {
-                //Todo: How to handle full season files? Currently the episode list is completely empty for these releases
-                //Todo: Should we assume that the release contains all the episodes that belong to this season and add them from the DB?
-                //Todo: Fix this so it properly handles multi-epsiode releases (Currently as long as the first episode is needed we download it)
-                //Todo: for small releases this is less of an issue, but for Full Season Releases this could be an issue if we only need the first episode (or first few)
-
-                if (!series.Monitored)
-                {
-                    Logger.Debug("{0} is present in the DB but not tracked. skipping.", parseResult.CleanTitle);
-                    return false;
-                }
+                Logger.Debug("{0} is present in the DB but not tracked. skipping.", parseResult.CleanTitle);
+                return false;
+            }
 
-                if (!_seriesProvider.QualityWanted(series.SeriesId, parseResult.Quality))
-                {
-                    Logger.Debug("Post doesn't meet the quality requirements [{0}]. skipping.", parseResult.Quality);
-                    return false;
-                }
+            if (!_seriesProvider.QualityWanted(series.SeriesId, parseResult.Quality))
+            {
+                Logger.Debug("Post doesn't meet the quality requirements [{0}]. skipping.", parseResult.Quality);
+                return false;
+            }
 
-                if (_seasonProvider.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
-                {
-                    Logger.Debug("Season {0} is currently set to ignore. skipping.", parseResult.SeasonNumber);
-                    return false;
-                }
+            if (_seasonProvider.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
+            {
+                Logger.Debug("Season {0} is currently set to ignore. skipping.", parseResult.SeasonNumber);
+                return false;
+            }
 
+            foreach (var episodeNumber in parseResult.EpisodeNumbers)
+            {
                 var episodeInfo = _episodeProvider.GetEpisode(series.SeriesId, parseResult.SeasonNumber, episodeNumber);
                 if (episodeInfo == null)
                 {
@@ -84,21 +81,33 @@ namespace NzbDrone.Core.Providers.Indexer
                     _episodeProvider.AddEpisode(episodeInfo);
                 }
 
+                parseResult.Episodes.Add(episodeInfo);
+            }
 
-                if (!_episodeProvider.IsNeeded(parseResult, episodeInfo))
+            foreach (var episode in parseResult.Episodes)
+            {
+                //Todo: How to handle full season files? Currently the episode list is completely empty for these releases
+                //Todo: Should we assume that the release contains all the episodes that belong to this season and add them from the DB?
+                //Todo: Fix this so it properly handles multi-epsiode releases (Currently as long as the first episode is needed we download it)
+                //Todo: for small releases this is less of an issue, but for Full Season Releases this could be an issue if we only need the first episode (or first few)
+
+
+
+                if (!_episodeProvider.IsNeeded(parseResult, episode))
                 {
                     Logger.Debug("Episode {0} is not needed. skipping.", parseResult);
-                    return false;
+                    continue;
                 }
 
-                if (_historyProvider.Exists(episodeInfo.EpisodeId, parseResult.Quality, parseResult.Proper))
+                if (_historyProvider.Exists(episode.EpisodeId, parseResult.Quality, parseResult.Proper))
                 {
                     Logger.Debug("Episode {0} is in history. skipping.", parseResult);
-                    return false;
+                    continue;
                 }
 
                 //Congragulations younge feed item! you have made it this far. you are truly special!!!
                 Logger.Debug("Episode {0} is needed", parseResult);
+
                 return true;
             }
 
diff --git a/NzbDrone.Core/Providers/MediaFileProvider.cs b/NzbDrone.Core/Providers/MediaFileProvider.cs
index 56b3a433c..0879692e7 100644
--- a/NzbDrone.Core/Providers/MediaFileProvider.cs
+++ b/NzbDrone.Core/Providers/MediaFileProvider.cs
@@ -83,7 +83,7 @@ namespace NzbDrone.Core.Providers
                     var episodes = new List<Episode>();
 
                     //Check for daily shows
-                    if (parseResult.Episodes == null)
+                    if (parseResult.EpisodeNumbers == null)
                     {
                         var episode = _episodeProvider.GetEpisode(series.SeriesId, parseResult.AirDate.Date);
 
@@ -98,7 +98,7 @@ namespace NzbDrone.Core.Providers
                     }
                     else
                     {
-                        foreach (var episodeNumber in parseResult.Episodes)
+                        foreach (var episodeNumber in parseResult.EpisodeNumbers)
                         {
                             var episode = _episodeProvider.GetEpisode(series.SeriesId, parseResult.SeasonNumber,
                                                                       episodeNumber);
diff --git a/NzbDrone.Core/Providers/SabProvider.cs b/NzbDrone.Core/Providers/SabProvider.cs
index 6a7c52f0b..8417eef9b 100644
--- a/NzbDrone.Core/Providers/SabProvider.cs
+++ b/NzbDrone.Core/Providers/SabProvider.cs
@@ -92,13 +92,13 @@ namespace NzbDrone.Core.Providers
                                  _configProvider.SabPassword);
         }
 
-        public String GetSabTitle(EpisodeParseResult parseResult)
+        public virtual String GetSabTitle(EpisodeParseResult parseResult)
         {
             //Show Name - 1x01-1x02 - Episode Name
             //Show Name - 1x01 - Episode Name
             var episodeString = new List<String>();
 
-            foreach (var episode in parseResult.Episodes)
+            foreach (var episode in parseResult.EpisodeNumbers)
             {
                 episodeString.Add(String.Format("{0}x{1}", parseResult.SeasonNumber, episode));
             }
diff --git a/NzbDrone.Web/Controllers/SeriesController.cs b/NzbDrone.Web/Controllers/SeriesController.cs
index 247786d8a..b2a21a837 100644
--- a/NzbDrone.Web/Controllers/SeriesController.cs
+++ b/NzbDrone.Web/Controllers/SeriesController.cs
@@ -142,15 +142,14 @@ namespace NzbDrone.Web.Controllers
             return View(new GridModel(episodes));
         }
 
-        [GridAction]
-        public ActionResult _CustomBinding(GridCommand command, int seasonId)
+        //Local Helpers
+        private string GetEpisodePath(EpisodeFile file)
         {
-            IEnumerable<Episode> data = GetData(command);
-            return View(new GridModel
-                            {
-                                Data = data,
-                                Total = data.Count()
-                            });
+            if (file == null)
+                return String.Empty;
+
+            //Return the path relative to the Series' Folder
+            return file.Path.Replace(file.Series.Path, "").Trim(Path.DirectorySeparatorChar);
         }
 
         public ActionResult SearchForSeries(string seriesName)
@@ -174,66 +173,6 @@ namespace NzbDrone.Web.Controllers
             return PartialView("SeriesSearchResults", model);
         }
 
-        private IEnumerable<Episode> GetData(GridCommand command)
-        {
-            return null;
-            /*    
-            IQueryable<Episode> data = .Orders;
-            //Apply filtering
-            if (command.FilterDescriptors.Any())
-            {
-                data = data.Where(ExpressionBuilder.Expression<Order>(command.FilterDescriptors));
-            }
-            // Apply sorting
-            foreach (SortDescriptor sortDescriptor in command.SortDescriptors)
-            {
-                if (sortDescriptor.SortDirection == ListSortDirection.Ascending)
-                {
-                    switch (sortDescriptor.Member)
-                    {
-                        case "OrderID":
-                            data = data.OrderBy(ExpressionBuilder.Expression<Order, int>(sortDescriptor.Member));
-                            break;
-                        case "Customer.ContactName":
-                            data = data.OrderBy(order => order.Customer.ContactName);
-                            break;
-                        case "ShipAddress":
-                            data = data.OrderBy(order => order.ShipAddress);
-                            break;
-                        case "OrderDate":
-                            data = data.OrderBy(order => order.OrderDate);
-                            break;
-                    }
-                }
-                else
-                {
-                    switch (sortDescriptor.Member)
-                    {
-                        case "OrderID":
-                            data = data.OrderByDescending(order => order.OrderID);
-                            break;
-                        case "Customer.ContactName":
-                            data = data.OrderByDescending(order => order.Customer.ContactName);
-                            break;
-                        case "ShipAddress":
-                            data = data.OrderByDescending(order => order.ShipAddress);
-                            break;
-                        case "OrderDate":
-                            data = data.OrderByDescending(order => order.OrderDate);
-                            break;
-                    }
-                }
-            }
-            count = data.Count();
-            // ... and paging
-            if (command.PageSize > 0)
-            {
-                data = data.Skip((command.Page - 1) * command.PageSize);
-            }
-            data = data.Take(command.PageSize);
-            return data;*/
-        }
-
         [AcceptVerbs(HttpVerbs.Post)]
         [GridAction]
         public ActionResult _SaveAjaxEditing(string id)
@@ -301,16 +240,6 @@ namespace NzbDrone.Web.Controllers
             return RedirectToAction("Index");
         }
 
-        //Local Helpers
-        private string GetEpisodePath(EpisodeFile file)
-        {
-            if (file == null)
-                return String.Empty;
-
-            //Return the path relative to the Series' Folder
-            return file.Path.Replace(file.Series.Path, "").Trim(Path.DirectorySeparatorChar);
-        }
-
         private List<SeriesModel> GetSeriesModels(List<Series> seriesInDb)
         {
             var series = new List<SeriesModel>();
diff --git a/NzbDrone.Web/Views/Series/Details.cshtml b/NzbDrone.Web/Views/Series/Details.cshtml
index 75aec3d94..d29f74dd1 100644
--- a/NzbDrone.Web/Views/Series/Details.cshtml
+++ b/NzbDrone.Web/Views/Series/Details.cshtml
@@ -58,45 +58,47 @@
     {
 
         <br />
-        <h3>Season @season.SeasonNumber</h3>
+        <h3>
+            Season @season.SeasonNumber</h3>
         <div class="grid-container">
             @{Season season1 = season;
-            Html.Telerik().Grid<EpisodeModel>().Name("seasons_" + season.SeasonNumber)
-                .TableHtmlAttributes(new { @class = "Grid" })
-                .Columns(columns =>
-                             {
-                                 columns.Bound(o => o.EpisodeId)
-                                     .ClientTemplate(
-                                         "<input type='checkbox' name='checkedEpisodes' value='<#= EpisodeId #>' />")
-                                     .Title("")
-                                     .Width(1)
-                                     .HtmlAttributes(new { style = "text-align:center" });
+              Html.Telerik().Grid<EpisodeModel>().Name("seasons_" + season.SeasonNumber)
+                  .TableHtmlAttributes(new { @class = "Grid" })
+                  .Columns(columns =>
+                               {
+                                   columns.Bound(o => o.EpisodeId)
+                                       .ClientTemplate(
+                                           "<input type='checkbox' name='checkedEpisodes' value='<#= EpisodeId #>' />")
+                                       .Title("")
+                                       .Width(1)
+                                       .HtmlAttributes(new { style = "text-align:center" });
 
-                                 columns.Bound(c => c.EpisodeNumber).Width(10).Title("Episode");
-                                 columns.Bound(c => c.Title).Title("Title").Width(300);
-                                 columns.Bound(c => c.AirDate).Format("{0:d}").Width(10);
-                                 columns.Bound(c => c.Quality).Width(10);
-                                 columns.Bound(c => c.Path);
-                                 columns.Bound(c => c.Status);
-                             })
-                .DetailView(detailView => detailView.ClientTemplate("<div><#= Overview #> </br><#= Path #> </div>"))
-                .ClientEvents(clientEvents =>
-                {
-                    clientEvents.OnDataBinding("grid_bind");
-                    clientEvents.OnDataBound("grid_bound");
-                })
-                .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(true))
-                .Footer(true)
-                .DataBinding(
-                    d =>
-                    d.Ajax().Select("_AjaxSeasonGrid", "Series",
-                                    new RouteValueDictionary { { "seasonId", season1.SeasonId.ToString() } }))
-                .ToolBar(
-                    c =>
-                    c.Custom().Text("Rename Season").Action("RenameSeason", "Series", new { seasonId = season1.SeasonId })
-                        .ButtonType(GridButtonType.Text))
-                .Render();}
-                <span class="grid-loader"><img src="@Url.Content("~/Content/Images/Loading.gif")" alt="Loading"/> Loading...</span>
+                                   columns.Bound(c => c.EpisodeNumber).Width(0).Title("Episode");
+                                   columns.Bound(c => c.Title).Title("Title");
+                                   columns.Bound(c => c.AirDate).Format("{0:d}").Width(0);
+                                   columns.Bound(c => c.Quality).Width(0);
+                                   columns.Bound(c => c.Status).Width(0);
+                               })
+                  .DetailView(detailView => detailView.ClientTemplate("<div><#= Overview #> </br><#= Path #> </div>"))
+                  .ClientEvents(clientEvents =>
+                  {
+                      clientEvents.OnDataBinding("grid_bind");
+                      clientEvents.OnDataBound("grid_bound");
+                  })
+                  .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(true))
+                  .Footer(true)
+                  .DataBinding(
+                      d =>
+                      d.Ajax().Select("_AjaxSeasonGrid", "Series",
+                                      new RouteValueDictionary { { "seasonId", season1.SeasonId.ToString() } }))
+                  .ToolBar(
+                      c =>
+                      c.Custom().Text("Rename Season").Action("RenameSeason", "Series", new { seasonId = season1.SeasonId })
+                          .ButtonType(GridButtonType.Text))
+                  .Render();}
+            <span class="grid-loader">
+                <img src="@Url.Content("~/Content/Images/Loading.gif")" alt="Loading"/>
+                Loading...</span>
         </div>
     }
     @{var specialSeasons = Model.Seasons.Where(s => s.SeasonNumber == 0).FirstOrDefault();}
@@ -104,10 +106,11 @@
     {
 
         <br />
-        <h3>Specials</h3>
+        <h3>
+            Specials</h3>
         <div class="grid-container">
             @{Html.Telerik().Grid<EpisodeModel>().Name("seasons_specials")
-                    .TableHtmlAttributes(new {@class = "Grid"})
+                    .TableHtmlAttributes(new { @class = "Grid" })
                     .Columns(columns =>
                              {
                                  columns.Bound(o => o.EpisodeId)
@@ -118,10 +121,10 @@
                                      .HtmlAttributes(new { style = "text-align:center" });
 
                                  columns.Bound(c => c.EpisodeNumber).Width(10).Title("Episode");
-                                 columns.Bound(c => c.Title).Title("Title").Width(300);
+                                 columns.Bound(c => c.Title).Title("Title").Width(10000);
                                  columns.Bound(c => c.AirDate).Format("{0:d}").Width(10);
                                  columns.Bound(c => c.Quality).Width(10);
-                                 columns.Bound(c => c.Path);
+                                 columns.Bound(c => c.Status).Width(10);
                              })
                     .DetailView(detailView => detailView.ClientTemplate("<div><#= Overview #> </br><#= Path #> </div>"))
                     .ClientEvents(clientEvents =>
@@ -136,7 +139,9 @@
                         d.Ajax().Select("_AjaxSeasonGrid", "Series",
                                         new RouteValueDictionary { { "seasonId", specialSeasons.SeasonId.ToString() } }))
                     .Render(); }
-            <span class="grid-loader"><img src="@Url.Content("~/Content/Images/Loading.gif")" alt="Loading"/> Loading...</span>
+            <span class="grid-loader">
+                <img src="@Url.Content("~/Content/Images/Loading.gif")" alt="Loading"/>
+                Loading...</span>
         </div>
     }
 }