<commit_before>﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;

using Norma.Delta.Services;
using Norma.Eta.Extensions;
using Norma.Eta.Filters;
using Norma.Eta.Helpers;
using Norma.Eta.Models;
using Norma.Eta.Services;
using Norma.Gamma.Models;

using Prism.Mvvm;

using Channel = Norma.Delta.Models.Channel;
using Episode = Norma.Delta.Models.Episode;
using Slot = Norma.Delta.Models.Slot;

namespace Norma.Models
{
    // ReSharper disable once ClassNeverInstantiated.Global
    internal class AbemaState : BindableBase, INetworkCaptureRequestAware
    {
        private readonly AbemaApiClient _abemaApiHost;
        private readonly Configuration _configuration;
        private readonly DatabaseService _databaseService;
        private readonly IDisposable _disposable;

        private readonly List<IFilter> _filters = new List<IFilter>
        {
            new MBToSBFilter(),
            new CopyrightFilter(),
            new RoleFilter(),
            new InvalidBracesFilter(),
            new BracesFilter(),
            new SpaceFilter(),
            new EmptyFilter(),
            new SeparatorFilter()
        };

        private readonly TimetableService _timetableService;
        private string _slotId = "";

        public AbemaState(AbemaApiClient abemaApiHost, Configuration configuration, DatabaseService databaseService,
                          NetworkHandler networkHandler, TimetableService timetableService)
        {
            _abemaApiHost = abemaApiHost;
            _configuration = configuration;
            _databaseService = databaseService;
            _timetableService = timetableService;
            var interval = TimeSpan.FromSeconds(configuration.Root.Operation.UpdateIntervalOfProgram);

            using (var connector = databaseService.Connect())
                CurrentChannel = connector.Channels.Single(w => w.ChannelId == _configuration.Root.LastViewedChannelStr);
            _disposable = Observable.Timer(TimeSpan.Zero, interval).Subscribe(w => SyncEpisode());
            networkHandler.RegisterInstance(this, w => w.Url.StartsWith("https://api.abema.io/v1/slotAudience?"));
        }

        #region Implementation of INetworkCaptureRequestAware

        public void OnRequestHandling(NetworkEventArgs e)
        {
            var slotId = UrlHelper.ParseQuery(e.Url)["slotId"];
            if (_slotId == slotId)
                return;
            _slotId = slotId;
            Observable.Return(0).Subscribe(async w => await SyncProgram());
        }

        #endregion

        ~AbemaState()
        {
            _disposable.Dispose();
        }

        private async Task SyncProgram()
        {
            try
            {
                Slot currentSlot;
                using (var connection = _databaseService.Connect())
                {
                    var datetime = DateTime.Now;

                    // このクエリだけ Lazy Loading を Off にしておく(SQLite だと Include 連結できない)
                    connection.TurnOffLazyLoading();
                    // ReSharper disable once ReplaceWithSingleCallToFirstOrDefault
                    currentSlot = connection.Slots.AsNoTracking()
                                            .Where(w => w.Channel.ChannelId == CurrentChannel.ChannelId)
                                            .Where(w => w.StartAt <= datetime && datetime <= w.EndAt)
                                            .Include(w => w.Episodes)
                                            .FirstOrDefault();
                }
                if (currentSlot == null)
                {
                    CurrentSlot = null;
                    CurrentEpisode = null;
                    return;
                }

                if (CurrentSlot?.SlotId != currentSlot.SlotId)
                {
                    var currentDetail = await _abemaApiHost.CurrentSlot(currentSlot.SlotId);
                    if (currentSlot.Episodes.Count != currentDetail.Programs.Length)
                    {
                        // Ep.2 ~ を更新
                        UpdateEpisode(currentSlot, currentDetail.Programs);
                        CurrentSlot = currentSlot;
                    }
                    // キャスト情報などを更新<commit_msg>Bug fix<commit_after>﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;

using Norma.Delta.Services;
using Norma.Eta.Extensions;
using Norma.Eta.Filters;
using Norma.Eta.Helpers;
using Norma.Eta.Models;
using Norma.Eta.Services;
using Norma.Gamma.Models;

using Prism.Mvvm;

using Channel = Norma.Delta.Models.Channel;
using Episode = Norma.Delta.Models.Episode;
using Slot = Norma.Delta.Models.Slot;

namespace Norma.Models
{
    // ReSharper disable once ClassNeverInstantiated.Global
    internal class AbemaState : BindableBase, INetworkCaptureRequestAware
    {
        private readonly AbemaApiClient _abemaApiHost;
        private readonly Configuration _configuration;
        private readonly DatabaseService _databaseService;
        private readonly IDisposable _disposable;

        private readonly List<IFilter> _filters = new List<IFilter>
        {
            new MBToSBFilter(),
            new CopyrightFilter(),
            new RoleFilter(),
            new InvalidBracesFilter(),
            new BracesFilter(),
            new SpaceFilter(),
            new EmptyFilter(),
            new SeparatorFilter()
        };

        private readonly TimetableService _timetableService;
        private string _slotId = "";

        public AbemaState(AbemaApiClient abemaApiHost, Configuration configuration, DatabaseService databaseService,
                          NetworkHandler networkHandler, TimetableService timetableService)
        {
            _abemaApiHost = abemaApiHost;
            _configuration = configuration;
            _databaseService = databaseService;
            _timetableService = timetableService;
            var interval = TimeSpan.FromSeconds(configuration.Root.Operation.UpdateIntervalOfProgram);

            using (var connector = databaseService.Connect())
                CurrentChannel = connector.Channels.Single(w => w.ChannelId == _configuration.Root.LastViewedChannelStr);
            _disposable = Observable.Timer(TimeSpan.Zero, interval).Subscribe(w => SyncEpisode());
            networkHandler.RegisterInstance(this, w => w.Url.StartsWith("https://api.abema.io/v1/slotAudience?"));
        }

        #region Implementation of INetworkCaptureRequestAware

        public void OnRequestHandling(NetworkEventArgs e)
        {
            var slotId = UrlHelper.ParseQuery(e.Url)["slotId"];
            if (_slotId == slotId)
                return;
            _slotId = slotId;
            Observable.Return(0).Subscribe(async w => await SyncProgram());
        }

        #endregion

        ~AbemaState()
        {
            _disposable.Dispose();
        }

        private async Task SyncProgram()
        {
            try
            {
                Slot currentSlot;
                using (var connection = _databaseService.Connect())
                {
                    // このクエリだけ Lazy Loading を Off にしておく(SQLite だと Include 連結できない)
                    connection.TurnOffLazyLoading();
                    // ReSharper disable once ReplaceWithSingleCallToFirstOrDefault
                    currentSlot = connection.Slots.AsNoTracking()
                                            .Where(w => w.SlotId == _slotId)
                                            .Include(w => w.Episodes)
                                            .FirstOrDefault();
                }
                if (currentSlot == null)
                {
                    CurrentSlot = null;
                    CurrentEpisode = null;
                    return;
                }

                if (CurrentSlot?.SlotId != currentSlot.SlotId)
                {
                    var currentDetail = await _abemaApiHost.CurrentSlot(currentSlot.SlotId);
                    if (currentSlot.Episodes.Count != currentDetail.Programs.Length)
                    {
                        // Ep.2 ~ を更新
                        UpdateEpisode(currentSlot, currentDetail.Programs);
                        CurrentSlot = currentSlot;
                    }
                    // キャスト情報などを更新
{'fraction_non_alphanumeric': 0.07788235294117647, 'fraction_numerical': 0.0007058823529411765, 'mean_word_length': 1.7744778067885119, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 20, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6180202', 'n_tokens_mistral': 2166, 'n_tokens_neox': 2060, 'n_words': 436}