예제 #1
0
        public AnimeEpisodeVM GetEpisodeForVideo(VideoDetailedVM vid, EpisodeList epList)
        {
            // get the episodes that this file applies to


            try
            {
                List <JMMServerBinary.Contract_AnimeEpisode> eps = JMMServerVM.Instance.clientBinaryHTTP.GetEpisodesForFile(vid.VideoLocalID,
                                                                                                                            JMMServerVM.Instance.CurrentUser.JMMUserID.Value);

                foreach (JMMServerBinary.Contract_AnimeEpisode epcontract in eps)
                {
                    foreach (object epObj in epList.lbEpisodes.ItemsSource)
                    {
                        AnimeEpisodeVM epItem = epObj as AnimeEpisodeVM;
                        if (epItem.AnimeEpisodeID == vid.AnimeEpisodeID)
                        {
                            return(epItem);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Utils.ShowErrorMessage(ex);
            }

            return(null);
        }
예제 #2
0
        public SeasonSeasonModel(String season)
        {
            var seasonPath = Paths.SeasonPath(Paths.Json, season);

            Season      = new Season(seasonPath);
            EpisodeList = Season.EpisodeList;

            if (!Config.IsAuthor && EpisodeList.Any())
            {
                var publishedEpisodes = EpisodeList
                                        .Where(e => e.IsPublished()).ToList();

                var nextSeason       = ((char)(season[0] + 1)).ToString();
                var nextSeasonExists = Paths.SeasonPathExists(Paths.Json, nextSeason);

                if (!nextSeasonExists)
                {
                    var lastEpisode = publishedEpisodes.Last();
                    publishedEpisodes.Remove(lastEpisode);
                }

                EpisodeList = publishedEpisodes
                              .Where(e => e.HasSummary())
                              .ToList();
            }
        }
예제 #3
0
        //public CommonCommand RefreshToDoListCommand
        //{
        //    get
        //    {
        //        return new CommonCommand((o) =>
        //        {
        //            RefreshToDoList();
        //        });
        //    }
        //}
        public override void LoadInfo()
        {
            EpisodeList.Clear();
            TargetObject.EpisodeList.ForEach(v =>
            {
                EpisodeList.Add(new EpisodeViewModel()
                {
                    TargetObject = v
                });
            });
            SceneList.Clear();
            TargetObject.SceneList.ForEach(v =>
            {
                SceneList.Add(new SceneViewModel()
                {
                    TargetObject = v
                });
            });
            NoteList.Clear();
            TargetObject.NoteList.ForEach(v => NoteList.Add(new NoteViewModel()
            {
                TargetObject = v
            }));

            //RefreshToDoList();

            base.LoadInfo();
        }
예제 #4
0
        // Updates the data of a specific podcast
        private void btnUpdatePod_Click(object sender, EventArgs e)
        {
            try
            {
                string title = lvPods.SelectedItems[0].SubItems[1].Text;

                string url             = tbUrl.Text;
                string category        = cbCategory.Text;
                var    stringFrequency = cbFrequency.SelectedItem;

                if (Validator.StringNotEmpty(title) &&
                    Validator.StringNotEmpty(category) &&
                    Validator.ParseFrequency(stringFrequency))
                {
                    int frequency = Int32.Parse(stringFrequency.ToString());

                    PodcastList.DeletePod(title);
                    EpisodeList.DeleteEpisodes(title);

                    DataLayerAccessor.AddPodcast(url, category, frequency);
                    DataLayerAccessor.CreateFiles();

                    UpdatePodListView();
                    lvEpisodes.Items.Clear();
                    tbEpDescription.Clear();
                    MessageBox.Show("Podcasten uppdaterades!", "Wohoo!", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch
            {
                MessageBox.Show("Ingen podcast är vald.", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
예제 #5
0
        // New RSS feed
        public static void RssFeed(string url, string cat, int freq)
        {
            // Reading the feed
            XmlReader       reader = XmlReader.Create(url);
            SyndicationFeed feed   = SyndicationFeed.Load(reader);

            reader.Close();

            // Creating a Podcast object and adding it to PodcastList
            string podTitle = feed.Title.Text;
            int    nrOfEp   = feed.Items.Count();

            Podcast podcast = new Podcast(url, nrOfEp, podTitle, cat, freq);

            PodcastList.AddPodcast(podcast);

            // Creating the Episodes objects and adding them to PodcastEpList
            foreach (SyndicationItem item in feed.Items)
            {
                string title       = item.Title.Text;
                string description = item.Summary.Text;

                Episode episode = new Episode(podTitle, title, description);
                EpisodeList.AddEpisode(episode);
            }

            TheTimer.SetTimer(url, podTitle, cat, freq);
        }
예제 #6
0
파일: DLHandler.cs 프로젝트: joabkidane/RSS
        public static void GetPodcastFromRss(string category, int updateFrequency, string url)
        {
            using (var reader = XmlReader.Create(url))
            {
                try
                {
                    var feed         = SyndicationFeed.Load(reader);
                    var podcastName  = feed.Title.Text;
                    int episodeCount = 0;
                    foreach (SyndicationItem s in feed.Items)
                    {
                        var episodeName = s.Title.Text;
                        var detail      = s.Summary.Text;
                        var episode     = new Episode(episodeName, podcastName, detail);
                        EpisodeList.Add(episode);
                        episodeCount++;
                    }

                    PodcastList.AddPodcast(new Podcast(podcastName, category, updateFrequency, episodeCount, url));
                    PodcastUpdate.pUpdate(podcastName, category, updateFrequency, url);
                }
                catch (Exception)
                {
                    System.Windows.Forms.MessageBox.Show("Cannot read RSS");
                }
            }
        }
예제 #7
0
        //Genomför en uppdatering av en podcast med en uppdaterad feed
        private PodCast PerformPodUpdate(PodCast p, SyndicationFeed updatedFeed)
        {
            p.Name        = updatedFeed.Title.Text;
            p.LastUpdated = updatedFeed.LastUpdatedTime;
            p.Episodes    = EpisodeList <Episode> .FromSyndicationItems(updatedFeed.Items);

            return(p);
        }
예제 #8
0
        public ShowPage()
        {
            this.InitializeComponent();

            DataContext = new ShowPageViewModel();

            EpisodeList.RegisterPropertyChangedCallback(ItemsControl.ItemsSourceProperty, OnItemsSourceChanged);
        }
예제 #9
0
        private void UpdaterTBoxEpisodeDetail(string episode)
        {
            var episodelist = EpisodeList.GetEpisodes().Where(p => p.EpisodeName.Equals(episode)).ToList();

            foreach (var ep in episodelist)
            {
                rTBoxEpisodeDetail.Text = ep.overrideEpisodeDetail();
            }
        }
예제 #10
0
        public MainPage()
        {
            this.InitializeComponent();

            this.NavigationCacheMode = NavigationCacheMode.Required;

            DataContext = new MainPageViewModel();

            EpisodeList.RegisterPropertyChangedCallback(ItemsControl.ItemsSourceProperty, OnItemsSourceChanged);
        }
예제 #11
0
        //Uppdaterar listan med podcastavsnitt
        private void UpdateEpisodeList(PodCast feed)
        {
            EpisodeList <Episode> epList = feed.Episodes;

            lvPodCastEpisodes.Items.Clear();
            lvPodCastEpisodes.Items.AddRange(epList.ToListViewItems());
            if (epList != null && epList.Count > 0)
            {
                UpdateEpisodeDetails(epList.Get(0));
            }
        }
예제 #12
0
        public void UpdatePodcasts(string podcast)
        {
            int updatefrequency = Convert.ToInt32(comboBoxUpdateFrequency.Text.Split(' ')[0]);

            PodcastList.RemovePodcast(podcast);
            EpisodeList.RemoveEpisode(podcast);
            Podcast.AddPodcast(comboBoxCategory.Text, updatefrequency, textBoxUrl.Text);

            UpdatelistViewPodcast();
            listViewEpisodes.Items.Clear();
            rTBoxEpisodeDetail.Clear();
        }
예제 #13
0
파일: DLHandler.cs 프로젝트: joabkidane/RSS
 public static void SaveEpisodes()
 {
     if (File.Exists("episode.txt"))
     {
         File.Delete("episode.txt");
     }
     using (Stream stream = File.OpenWrite(Environment.CurrentDirectory + "\\episode.txt"))
     {
         new XmlSerializer(typeof(List <Episode>)).Serialize(stream, EpisodeList.GetEpisodes());
         stream.Close();
     }
 }
예제 #14
0
 private void btnDelete_Click(object sender, EventArgs e)
 {
     try
     {
         string podcast = listViewPodcast.SelectedItems[0].Text;
         PodcastList.RemovePodcast(podcast);
         EpisodeList.RemoveEpisode(podcast);
         UpdatelistViewPodcast();
     }
     catch (Exception)
     {
         MessageBox.Show("You must select the podcast you want to delete!");
     }
 }
예제 #15
0
        private void UpdatelistViewEpisodes(string podcast)
        {
            var episodelist = EpisodeList.GetEpisodes().Where(titel => titel.PodcastName == podcast).ToList();

            listViewEpisodes.Items.Clear();
            for (int i = 0; i < episodelist.Count; i++)
            {
                Episode episode = episodelist[i];
                var     list    = new ListViewItem(new[]
                {
                    episode.EpisodeName
                });
                listViewEpisodes.Items.Add(list);
            }
        }
예제 #16
0
파일: DLHandler.cs 프로젝트: joabkidane/RSS
 public static void CreateEpisodes()
 {
     if (File.Exists("episode.txt"))
     {
         XDocument.Load("episode.txt").Descendants("Episode").Select(p => new
         {
             episodeName   = p.Element("EpisodeName").Value,
             podcastName   = p.Element("PodcastName").Value,
             episodeDetail = p.Element("EpisodeDetail").Value,
         }).ToList().ForEach(p =>
         {
             EpisodeList.Add(new Episode(p.episodeName, p.podcastName, p.episodeDetail));
         });
     }
 }
예제 #17
0
        // Creates the episode file and puts data into it.
        public static void CreateEpisodeFile()
        {
            // Deleted the file if found to not leave old data in it and cause errors
            if (File.Exists(currentDirectory + "\\data\\Episodes.txt"))
            {
                File.Delete(currentDirectory + "\\data\\Episodes.txt");
            }

            //Creating the file
            Stream stream = File.OpenWrite(currentDirectory + "\\data\\Episodes.txt");

            // Writing to the file
            XmlSerializer serializer = new XmlSerializer(typeof(List <Episode>));

            serializer.Serialize(stream, EpisodeList.GetEpList());
            stream.Close();
        }
예제 #18
0
        private void SwitchButtonClick(object sender, RoutedEventArgs e)
        {
            var button  = (Button)sender;
            var subject = (Model.SubjectLarge)DataContext;

            if (button.Content.ToString() == "SP")
            {
                EpisodeItemsControl.ItemsSource = subject.eps_special;
            }
            else
            {
                var item  = (sender as FrameworkElement).DataContext;
                var index = SwitchButtonListView.Items.IndexOf(item);
                EpisodeItemsControl.ItemsSource = subject.eps_normal;
                EpisodeList.ScrollToVerticalOffset(index * 100 * 40);
            }
        }
예제 #19
0
        // Updates the text box of the Description
        public void UpdateEpisodeDescription(string title)
        {
            string description = "";

            List <Episode> list = EpisodeList.GetEpList();

            foreach (Episode ep in list)
            {
                if (ep.Title == title)
                {
                    description = ep.Description;
                    break;
                }
            }

            tbEpDescription.Clear();
            tbEpDescription.AppendText(description);
        }
예제 #20
0
        // Updates the list view of the Episodes
        public void UpdateEpisodeListView(string title)
        {
            lvEpisodes.Items.Clear();

            List <Episode> epList = EpisodeList.GetEpList();

            foreach (var ep in epList)
            {
                if (ep.PodTitle == title)
                {
                    var list = new ListViewItem(new[]
                    {
                        ep.Title
                    });

                    lvEpisodes.Items.Add(list);
                }
            }
        }
예제 #21
0
        public override void SaveInfo()
        {
            TargetObject.SceneList.Clear();
            foreach (var s in SceneList)
            {
                TargetObject.SceneList.Add(s.TargetObject);
            }
            TargetObject.EpisodeList.Clear();
            EpisodeList.ToList().ForEach(v =>
            {
                TargetObject.EpisodeList.Add(v.TargetObject);
            });

            TargetObject.NoteList.Clear();
            NoteList.ToList().ForEach(v => TargetObject.NoteList.Add(v.TargetObject));

            //TargetObject.KeyWordList.Clear();
            //KeyWordList.ToList().ForEach(v => TargetObject.KeyWordList.Add(v));

            base.SaveInfo();
        }
예제 #22
0
        // Loads the file data and puts it into the episode list class
        public static void GetEpisodeList()
        {
            if (File.Exists("data\\Episodes.txt"))
            {
                XDocument xdoc = XDocument.Load("data\\Episodes.txt");

                xdoc.Descendants("Episode").Select(p => new
                {
                    podTitle = p.Element("PodTitle").Value,
                    title    = p.Element("Title").Value,
                    desc     = p.Element("Description").Value,
                }).ToList().ForEach(p =>
                {
                    Episode ep = new Episode(
                        p.podTitle,
                        p.title,
                        p.desc);
                    EpisodeList.AddEpisode(ep);
                });
            }
        }
예제 #23
0
        private void insertInEpisodeList(String file)
        {
            var dir = new DirectoryInfo(file);

            if (dir.Parent?.Parent == null)
            {
                return;
            }

            var episodeName = dir.Name;

            var seasonName = dir.Parent.Name.Replace("_", "");
            var path       = dir.Parent.Parent.FullName;

            var episode = Episode.Get(path, seasonName, episodeName);

            if (episode != null && episode.IsPublished())
            {
                EpisodeList.Add(episode);
            }
        }
예제 #24
0
        // The timer, NOT DONE!!!
        private static async void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e, string url, string title, string category, int frequency)
        {
            List <Podcast> list                = PodcastList.GetPodList();
            bool           PodExists           = false;
            int            NumberOfEpisodes    = 0;
            int            OldNumberOfEpisodes = await RssReader.GetNumberOfEpisodes(url);

            foreach (Podcast pod in list)
            {
                if (pod.Title == title)
                {
                    NumberOfEpisodes = pod.Episodes;
                    PodExists        = true;
                }
            }

            if (!PodExists)
            {
                timer.Enabled = false;
            }

            if (NumberOfEpisodes > OldNumberOfEpisodes)
            {
                PodcastList.DeletePod(title);
                EpisodeList.DeleteEpisodes(title);
                DataLayerAccessor.AddPodcast(url, category, frequency);
                CreateFile.CreatePodcastFile();
                CreateFile.CreateEpisodeFile();

                timer.Enabled = false;

                MessageBox.Show("Nytt avsnitt har hittats!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                MessageBox.Show("Inga nya avsnitt hittades!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            PodExists = false;
        }
예제 #25
0
        // Button to delete a podcast
        private void btnDeletePod_Click(object sender, EventArgs e)
        {
            try
            {
                string title = lvPods.SelectedItems[0].SubItems[1].Text;

                if (Validator.StringNotEmpty(title))
                {
                    PodcastList.DeletePod(title);
                    EpisodeList.DeleteEpisodes(title);
                    DataLayerAccessor.CreateFiles();

                    UpdatePodListView();
                    lvEpisodes.Items.Clear();
                    tbEpDescription.Clear();
                }
            }
            catch
            {
                MessageBox.Show("Ingen podcast är vald.", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
예제 #26
0
 internal void AddSeries(Uri fileUri, int fileSize, byte number)
 {
     EpisodeList.Add(new Episode($"Episode {number}", fileUri, fileSize, number));
 }
예제 #27
0
        public PodcastViewModel(IScreen hostScreen,
                                IPlayerModel player,
                                IEventAggregator eventAggregator,
                                IDialogService dialogService,
                                IFeedParser feedParser,
                                IChannelStore channelStore,
                                IPlaylistStore playlistStore)
            : base(eventAggregator)
        {
            HostScreen    = hostScreen;
            Player        = player;
            DialogService = dialogService;
            FeedParser    = feedParser;

            this.channelStore  = channelStore;
            this.playlistStore = playlistStore;

            GetChannelsCommand = ReactiveCommand.CreateFromTask(async _ => await GetChannels());
            GetChannelsCommand.IsExecuting.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => OnChannelsBusy(GetChannelsCommand.GetHashCode(), _));

            PlayItemCommand = ReactiveCommand.CreateFromTask <IPlayable>(async _ => await OnPlayEpisode(_ as Episode));

            // open url
            OpenUrlDialogCommand = ReactiveCommand.CreateFromTask(async _ => await OpenUrlDialog());
            OpenUrlDialogCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_LOAD));

            // channels busy indicator
            this.WhenAnyObservable(_ => _.ChannelsBusyList.CountChanged).DistinctUntilChanged()
            .Subscribe(_ => IsChannelsBusy = _ > 0);

            // episodes busy indicator
            this.WhenAnyObservable(_ => _.EpisodesBusyList.CountChanged).DistinctUntilChanged()
            .Subscribe(_ => IsEpisodesBusy = _ > 0);

            OpenUrlCommand = ReactiveCommand.CreateFromTask <string>(async _ => await OnOpenUrl(_));
            OpenUrlCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_LOAD));

            // load channel
            LoadChannelFromUrlCommand = ReactiveCommand.CreateFromTask <string>(LoadChannelFromUrlAsync);
            OpenUrlCommand.IsExecuting.ObserveOn(RxApp.MainThreadScheduler).Subscribe(_ =>
            {
                OnChannelsBusy(OpenUrlCommand.GetHashCode(), _);
                OnEpisodesBusy(OpenUrlCommand.GetHashCode(), _);
            });

            LoadChannelFromUrlCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_LOAD));

            // delete channel
            ConfirmDeleteChannelCommand = ReactiveCommand.CreateFromTask <Channel>(async _ => await ConfirmDelete(_));
            DeleteChannelCommand        = ReactiveCommand.CreateFromTask <Channel>(async _ => await DeleteChannel(_));
            DeleteChannelCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_DELETE));
            DeleteChannelCommand.IsExecuting.Subscribe(_ =>
            {
                OnChannelsBusy(DeleteChannelCommand.GetHashCode(), _);
                OnEpisodesBusy(DeleteChannelCommand.GetHashCode(), _);
            });

            var existsSelectedChannel = this.WhenAny(vm => vm.SelectedChannel, _ => SelectedChannel != null);

            this.WhenAnyValue(vm => vm.SelectedChannel).Select(_ => _ == null ? 0 : SelectedChannel.Id)
            .ToProperty(this, _ => _.SelectedChannelId, out selectedChannelId);
            RemoveFilterCommand = ReactiveCommand.Create <Unit>(_ => SelectedChannel = null, existsSelectedChannel);

            MarkAllPlayedCommand = ReactiveCommand.CreateFromTask <Channel>(async _ => await MarkChannelPlayed(_));

            CopyUrlCommand = ReactiveCommand.Create <Channel>(_ => Clipboard.SetText(_.Link));

            var episodeSet = this.WhenAnyValue(_ => _.SelectedEpisode);

            // detail
            this.WhenAnyValue(vm => vm.SelectedChannel).NotNull().Cast <IDetailEntity>()
            .Merge(episodeSet.Cast <IDetailEntity>())
            .ToProperty(this, _ => _.CurrentDetailEntity, out currentDetailEntity);

            this.WhenAnyValue(vm => vm.Player.LocateCurrent).NotNull()
            .Subscribe(c => c.Subscribe(_ => LocatePageForCurrent()));

            // episode list is loading
            this.WhenAnyValue(_ => _.EpisodeList.IsLoading).SubscribeOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => OnEpisodesBusy(EpisodeList.GetHashCode(), _));

            ScrollIntoView = ReactiveCommand.Create <int, int>(_ => _);

            // playlist
            AddToPlaylist = ReactiveCommand.CreateFromTask <Playlist>(async _ => await AddEpisodeToPlaylist(_));

            // sort order
            this.WhenAnyValue(_ => _.SelectedEpisodeSortOrder)
            .Subscribe(_ => EpisodeOrderBy.OnNext(GetEpisodeSortOrder(_)));
            ToggleSortDirectionCommand =
                ReactiveCommand.Create(
                    () => EpisodeOrderBy.OnNext(GetEpisodeSortOrder(SelectedEpisodeSortOrder, false)));

            // on channels changed
            this.WhenAnyValue(_ => _.Channels).NotNull().Subscribe(_ => OnChannelsChanged());

            // update channels
            var canUpdate = new BehaviorSubject <bool>(false);

            UpdateChannelsCommand = ReactiveCommand.CreateFromTask(async _ => await UpdateChannelsAsync(),
                                                                   canUpdate.DistinctUntilChanged());

            UpdateChannelsCommand.IsExecuting.CombineLatest(this.WhenAnyValue(_ => _.Channels.IsEmpty),
                                                            (exec, empty) => !exec && !empty && IsUpdateEnabled).DistinctUntilChanged()
            .Subscribe(_ => canUpdate.OnNext(_));

            UpdateChannelsCommand.IsExecuting.ObserveOn(RxApp.MainThreadScheduler).Subscribe(_ => IsUpdating = _);
            UpdateChannelsCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_UPDATE));

            // init episodes
            EpisodeList = InitEpisodeList();
            EpisodeList.Changed.Subscribe(_ => InitActivePlaylist());

            // detail
            ToggleShowDetailCommand = ReactiveCommand.Create <bool, bool>(_ => _);
            DeactivateCommand       = ReactiveCommand.Create(() => { });
        }
예제 #28
0
        public void UpdateStats(bool watchedStats, bool missingEpsStats, bool updateAllGroupsAbove)
        {
            DateTime start        = DateTime.Now;
            DateTime startOverall = DateTime.Now;

            logger.Info("Starting Updating STATS for SERIES {0} ({1} - {2} - {3})", this.ToString(), watchedStats, missingEpsStats, updateAllGroupsAbove);

            AnimeSeries_UserRepository      repSeriesUser  = new AnimeSeries_UserRepository();
            AnimeEpisode_UserRepository     repEpisodeUser = new AnimeEpisode_UserRepository();
            VideoLocalRepository            repVids        = new VideoLocalRepository();
            CrossRef_File_EpisodeRepository repXrefs       = new CrossRef_File_EpisodeRepository();

            JMMUserRepository repUsers = new JMMUserRepository();
            List <JMMUser>    allUsers = repUsers.GetAll();

            DateTime            startEps = DateTime.Now;
            List <AnimeEpisode> eps      = GetAnimeEpisodes();
            TimeSpan            tsEps    = DateTime.Now - startEps;

            logger.Trace("Got episodes for SERIES {0} in {1}ms", this.ToString(), tsEps.TotalMilliseconds);

            DateTime                     startVids = DateTime.Now;
            List <VideoLocal>            vidsTemp  = repVids.GetByAniDBAnimeID(this.AniDB_ID);
            List <CrossRef_File_Episode> crossRefs = repXrefs.GetByAnimeID(this.AniDB_ID);

            Dictionary <int, List <CrossRef_File_Episode> > dictCrossRefs = new Dictionary <int, List <CrossRef_File_Episode> >();

            foreach (CrossRef_File_Episode xref in crossRefs)
            {
                if (!dictCrossRefs.ContainsKey(xref.EpisodeID))
                {
                    dictCrossRefs[xref.EpisodeID] = new List <CrossRef_File_Episode>();
                }
                dictCrossRefs[xref.EpisodeID].Add(xref);
            }

            Dictionary <string, VideoLocal> dictVids = new Dictionary <string, VideoLocal>();

            foreach (VideoLocal vid in vidsTemp)
            {
                dictVids[vid.Hash] = vid;
            }

            TimeSpan tsVids = DateTime.Now - startVids;

            logger.Trace("Got video locals for SERIES {0} in {1}ms", this.ToString(), tsVids.TotalMilliseconds);


            if (watchedStats)
            {
                foreach (JMMUser juser in allUsers)
                {
                    //this.WatchedCount = 0;
                    AnimeSeries_User userRecord = GetUserRecord(juser.JMMUserID);
                    if (userRecord == null)
                    {
                        userRecord = new AnimeSeries_User(juser.JMMUserID, this.AnimeSeriesID);
                    }

                    // reset stats
                    userRecord.UnwatchedEpisodeCount = 0;
                    userRecord.WatchedEpisodeCount   = 0;
                    userRecord.WatchedCount          = 0;
                    userRecord.WatchedDate           = null;

                    DateTime startUser = DateTime.Now;
                    List <AnimeEpisode_User>            epUserRecords   = repEpisodeUser.GetByUserID(juser.JMMUserID);
                    Dictionary <int, AnimeEpisode_User> dictUserRecords = new Dictionary <int, AnimeEpisode_User>();
                    foreach (AnimeEpisode_User usrec in epUserRecords)
                    {
                        dictUserRecords[usrec.AnimeEpisodeID] = usrec;
                    }
                    TimeSpan tsUser = DateTime.Now - startUser;
                    logger.Trace("Got user records for SERIES {0}/{1} in {2}ms", this.ToString(), juser.Username, tsUser.TotalMilliseconds);

                    foreach (AnimeEpisode ep in eps)
                    {
                        // if the episode doesn't have any files then it won't count towards watched/unwatched counts
                        List <VideoLocal> epVids = new List <VideoLocal>();

                        if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID))
                        {
                            foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID])
                            {
                                if (xref.EpisodeID == ep.AniDB_EpisodeID)
                                {
                                    if (dictVids.ContainsKey(xref.Hash))
                                    {
                                        epVids.Add(dictVids[xref.Hash]);
                                    }
                                }
                            }
                        }
                        if (epVids.Count == 0)
                        {
                            continue;
                        }

                        if (ep.EpisodeTypeEnum == AniDBAPI.enEpisodeType.Episode || ep.EpisodeTypeEnum == AniDBAPI.enEpisodeType.Special)
                        {
                            AnimeEpisode_User epUserRecord = null;
                            if (dictUserRecords.ContainsKey(ep.AnimeEpisodeID))
                            {
                                epUserRecord = dictUserRecords[ep.AnimeEpisodeID];
                            }

                            if (epUserRecord != null && epUserRecord.WatchedDate.HasValue)
                            {
                                userRecord.WatchedEpisodeCount++;
                            }
                            else
                            {
                                userRecord.UnwatchedEpisodeCount++;
                            }

                            if (epUserRecord != null)
                            {
                                if (userRecord.WatchedDate.HasValue)
                                {
                                    if (epUserRecord.WatchedDate > userRecord.WatchedDate)
                                    {
                                        userRecord.WatchedDate = epUserRecord.WatchedDate;
                                    }
                                }
                                else
                                {
                                    userRecord.WatchedDate = epUserRecord.WatchedDate;
                                }

                                userRecord.WatchedCount += epUserRecord.WatchedCount;
                            }
                        }
                    }
                    repSeriesUser.Save(userRecord);
                }
            }

            TimeSpan ts = DateTime.Now - start;

            logger.Trace("Updated WATCHED stats for SERIES {0} in {1}ms", this.ToString(), ts.TotalMilliseconds);
            start = DateTime.Now;



            if (missingEpsStats)
            {
                enAnimeType animeType   = enAnimeType.TVSeries;
                AniDB_Anime aniDB_Anime = this.GetAnime();
                if (aniDB_Anime != null)
                {
                    animeType = aniDB_Anime.AnimeTypeEnum;
                }

                MissingEpisodeCount       = 0;
                MissingEpisodeCountGroups = 0;

                // get all the group status records
                AniDB_GroupStatusRepository repGrpStat  = new AniDB_GroupStatusRepository();
                List <AniDB_GroupStatus>    grpStatuses = repGrpStat.GetByAnimeID(this.AniDB_ID);

                // find all the episodes for which the user has a file
                // from this we can determine what their latest episode number is
                // find out which groups the user is collecting

                List <int> userReleaseGroups = new List <int>();
                foreach (AnimeEpisode ep in eps)
                {
                    List <VideoLocal> vids = new List <VideoLocal>();
                    if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID))
                    {
                        foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID])
                        {
                            if (xref.EpisodeID == ep.AniDB_EpisodeID)
                            {
                                if (dictVids.ContainsKey(xref.Hash))
                                {
                                    vids.Add(dictVids[xref.Hash]);
                                }
                            }
                        }
                    }

                    //List<VideoLocal> vids = ep.VideoLocals;
                    foreach (VideoLocal vid in vids)
                    {
                        AniDB_File anifile = vid.GetAniDBFile();
                        if (anifile != null)
                        {
                            if (!userReleaseGroups.Contains(anifile.GroupID))
                            {
                                userReleaseGroups.Add(anifile.GroupID);
                            }
                        }
                    }
                }

                int         latestLocalEpNumber = 0;
                EpisodeList epReleasedList      = new EpisodeList(animeType);
                EpisodeList epGroupReleasedList = new EpisodeList(animeType);

                foreach (AnimeEpisode ep in eps)
                {
                    //List<VideoLocal> vids = ep.VideoLocals;
                    if (ep.EpisodeTypeEnum != AniDBAPI.enEpisodeType.Episode)
                    {
                        continue;
                    }

                    List <VideoLocal> vids = new List <VideoLocal>();
                    if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID))
                    {
                        foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID])
                        {
                            if (xref.EpisodeID == ep.AniDB_EpisodeID)
                            {
                                if (dictVids.ContainsKey(xref.Hash))
                                {
                                    vids.Add(dictVids[xref.Hash]);
                                }
                            }
                        }
                    }



                    AniDB_Episode aniEp     = ep.AniDB_Episode;
                    int           thisEpNum = aniEp.EpisodeNumber;

                    if (thisEpNum > latestLocalEpNumber && vids.Count > 0)
                    {
                        latestLocalEpNumber = thisEpNum;
                    }

                    // does this episode have a file released
                    // does this episode have a file released by the group the user is collecting
                    bool epReleased      = false;
                    bool epReleasedGroup = false;
                    foreach (AniDB_GroupStatus gs in grpStatuses)
                    {
                        if (gs.LastEpisodeNumber >= thisEpNum)
                        {
                            epReleased = true;
                        }
                        if (userReleaseGroups.Contains(gs.GroupID) && gs.HasGroupReleasedEpisode(thisEpNum))
                        {
                            epReleasedGroup = true;
                        }
                    }


                    try
                    {
                        epReleasedList.Add(ep, (!epReleased || vids.Count != 0));
                        epGroupReleasedList.Add(ep, (!epReleasedGroup || vids.Count != 0));
                    }
                    catch (Exception e)
                    {
                        logger.Trace("Error {0}", e.ToString());
                        throw;
                    }
                }
                foreach (EpisodeList.StatEpisodes eplst in epReleasedList)
                {
                    if (!eplst.Available)
                    {
                        MissingEpisodeCount++;
                    }
                }
                foreach (EpisodeList.StatEpisodes eplst in epGroupReleasedList)
                {
                    if (!eplst.Available)
                    {
                        MissingEpisodeCountGroups++;
                    }
                }

                this.LatestLocalEpisodeNumber = latestLocalEpNumber;
            }

            ts = DateTime.Now - start;
            logger.Trace("Updated MISSING EPS stats for SERIES {0} in {1}ms", this.ToString(), ts.TotalMilliseconds);
            start = DateTime.Now;

            AnimeSeriesRepository rep = new AnimeSeriesRepository();

            rep.Save(this);

            if (updateAllGroupsAbove)
            {
                foreach (AnimeGroup grp in AllGroupsAbove)
                {
                    grp.UpdateStats(watchedStats, missingEpsStats);
                }
            }

            ts = DateTime.Now - start;
            logger.Trace("Updated GROUPS ABOVE stats for SERIES {0} in {1}ms", this.ToString(), ts.TotalMilliseconds);
            start = DateTime.Now;

            TimeSpan tsOverall = DateTime.Now - startOverall;

            logger.Info("Finished Updating STATS for SERIES {0} in {1}ms ({2} - {3} - {4})", this.ToString(), tsOverall.TotalMilliseconds,
                        watchedStats, missingEpsStats, updateAllGroupsAbove);
        }