<commit_before>//
//  DefaultNewsInteractor.swift
//  Eurofurence
//
//  Created by <NAME> on 23/04/2018.
//  Copyright © 2018 Eurofurence. All rights reserved.
//

import Foundation

private protocol NewsViewModelComponent {

    var childCount: Int { get }
    var title: String { get }

    func announceContent(at index: Int, to visitor: NewsViewModelVisitor)
    func announceValue(at index: Int, to completionHandler: @escaping (NewsViewModelValue) -> Void)

}

class DefaultNewsInteractor: NewsInteractor,
                             AuthenticationStateObserver,
                             PrivateMessagesServiceObserver,
                             ConventionCountdownServiceObserver,
                             EventsServiceObserver {

    // MARK: Properties

    private let announcementsService: AnnouncementsService
    private let authenticationService: AuthenticationService
    private let relativeTimeIntervalCountdownFormatter: RelativeTimeIntervalCountdownFormatter
    private var delegate: NewsInteractorDelegate?
    private var unreadMessagesCount = 0
    private var daysUntilConvention: Int?
    private var runningEvents = [Event2]()
    private var upcomingEvents = [Event2]()
    private var currentUser: User?

    // MARK: Initialization

    convenience init() {
        struct DummyEventsService: EventsService {
            func add(_ observer: EventsServiceObserver) {

            }
        }

        self.init(announcementsService: EurofurenceApplication.shared,
                  authenticationService: EurofurenceApplication.shared,
                  privateMessagesService: EurofurencePrivateMessagesService.shared,
                  daysUntilConventionService: EurofurenceApplication.shared,
                  eventsService: DummyEventsService(),
                  relativeTimeIntervalCountdownFormatter: FoundationRelativeTimeIntervalCountdownFormatter.shared)
    }

    init(announcementsService: AnnouncementsService,
         authenticationService: AuthenticationService,
         privateMessagesService: PrivateMessagesService,
         daysUntilConventionService: ConventionCountdownService,
         eventsService: EventsService,
         relativeTimeIntervalCountdownFormatter: RelativeTimeIntervalCountdownFormatter) {
        self.announcementsService = announcementsService
        self.authenticationService = authenticationService
        self.relativeTimeIntervalCountdownFormatter = relativeTimeIntervalCountdownFormatter

        authenticationService.add(self)
        privateMessagesService.add(self)
        daysUntilConventionService.add(self)
        eventsService.add(self)
    }

    // MARK: NewsInteractor

    func subscribeViewModelUpdates(_ delegate: NewsInteractorDelegate) {
        self.delegate = delegate
        regenerateViewModel()
    }

    // MARK: AuthenticationStateObserver

    func userDidLogin(_ user: User) {
        currentUser = user
        regenerateViewModel()
    }

    func userDidLogout() {
        currentUser = nil
        regenerateViewModel()
    }

    // MARK: PrivateMessagesServiceObserver

    func privateMessagesServiceDidUpdateUnreadMessageCount(to unreadCount: Int) {
        unreadMessagesCount = unreadCount
        regenerateViewModel()
    }

    func privateMessagesServiceDidFinishRefreshingMessages(_ messages: [Message]) {

    }

    func privateMessagesServiceDidFailToLoadMessages() {

    }

    // MARK: DaysUntilConventionServiceObserver

    func conventionCountdownStateDidChange(to state: ConventionCountdownState) {
        switch state {
        case .countingDown(let daysRemaining):
            daysUntilConvention = daysRemaining

        case .countdownElapsed:
            daysUntilConvention = nil
        }

        regenerateViewModel()
    }

    // MARK: EventsServiceObserver

    func eurofurenceApplicationDidUpdateRunningEvents(to events: [Event2]) {
        runningEvents = events
        regenerateViewModel()
    }

    func eurofurenceApplicationDidUpdateUpcomingEvents(to events: [Event2]) {
        upcomingEvents = events
        regenerateViewModel()
    }

    // MARK: Private

    private func regenerateViewModel() {
//        makeUserWidgetViewModel { (userWidgetViewModel) in
        let userWidgetViewModel = makeUserWidgetViewModel()
            self.announcementsService.fetchAnnouncements { (announcements) in
                var components = [NewsViewModelComponent]()
                components.append(UserComponent(viewModel: userWidgetViewModel))

                if let daysUntilConvention = self.daysUntilConvention {
                    components.append(CountdownComponent(daysUntilConvention: daysUntilConvention))
                }

                components.append(AnnouncementsComponent(announcements: announcements))

                if self.daysUntilConvention == nil {
                    if !self.upcomingEvents.isEmpty {
                        components.append(EventsComponent(title: .upcomingEvents, events: self.upcomingEvents, relativeTimeFormatter: self.relativeTimeIntervalCountdownFormatter))
                    }

                    if !self.runningEvents.isEmpty {
                        components.append(EventsComponent(title: .runningEvents, events: self.runningEvents, relativeTimeFormatter: self.relativeTimeIntervalCountdownFormatter))
                    }
                }

                let viewModel = ViewModel(components: components)
                self.delegate?.viewModelDidUpdate(viewModel)
            }
//        }<commit_msg>Remove commented out code<commit_after>//
//  DefaultNewsInteractor.swift
//  Eurofurence
//
//  Created by <NAME> on 23/04/2018.
//  Copyright © 2018 Eurofurence. All rights reserved.
//

import Foundation

private protocol NewsViewModelComponent {

    var childCount: Int { get }
    var title: String { get }

    func announceContent(at index: Int, to visitor: NewsViewModelVisitor)
    func announceValue(at index: Int, to completionHandler: @escaping (NewsViewModelValue) -> Void)

}

class DefaultNewsInteractor: NewsInteractor,
                             AuthenticationStateObserver,
                             PrivateMessagesServiceObserver,
                             ConventionCountdownServiceObserver,
                             EventsServiceObserver {

    // MARK: Properties

    private let announcementsService: AnnouncementsService
    private let authenticationService: AuthenticationService
    private let relativeTimeIntervalCountdownFormatter: RelativeTimeIntervalCountdownFormatter
    private var delegate: NewsInteractorDelegate?
    private var unreadMessagesCount = 0
    private var daysUntilConvention: Int?
    private var runningEvents = [Event2]()
    private var upcomingEvents = [Event2]()
    private var currentUser: User?

    // MARK: Initialization

    convenience init() {
        struct DummyEventsService: EventsService {
            func add(_ observer: EventsServiceObserver) {

            }
        }

        self.init(announcementsService: EurofurenceApplication.shared,
                  authenticationService: EurofurenceApplication.shared,
                  privateMessagesService: EurofurencePrivateMessagesService.shared,
                  daysUntilConventionService: EurofurenceApplication.shared,
                  eventsService: DummyEventsService(),
                  relativeTimeIntervalCountdownFormatter: FoundationRelativeTimeIntervalCountdownFormatter.shared)
    }

    init(announcementsService: AnnouncementsService,
         authenticationService: AuthenticationService,
         privateMessagesService: PrivateMessagesService,
         daysUntilConventionService: ConventionCountdownService,
         eventsService: EventsService,
         relativeTimeIntervalCountdownFormatter: RelativeTimeIntervalCountdownFormatter) {
        self.announcementsService = announcementsService
        self.authenticationService = authenticationService
        self.relativeTimeIntervalCountdownFormatter = relativeTimeIntervalCountdownFormatter

        authenticationService.add(self)
        privateMessagesService.add(self)
        daysUntilConventionService.add(self)
        eventsService.add(self)
    }

    // MARK: NewsInteractor

    func subscribeViewModelUpdates(_ delegate: NewsInteractorDelegate) {
        self.delegate = delegate
        regenerateViewModel()
    }

    // MARK: AuthenticationStateObserver

    func userDidLogin(_ user: User) {
        currentUser = user
        regenerateViewModel()
    }

    func userDidLogout() {
        currentUser = nil
        regenerateViewModel()
    }

    // MARK: PrivateMessagesServiceObserver

    func privateMessagesServiceDidUpdateUnreadMessageCount(to unreadCount: Int) {
        unreadMessagesCount = unreadCount
        regenerateViewModel()
    }

    func privateMessagesServiceDidFinishRefreshingMessages(_ messages: [Message]) {

    }

    func privateMessagesServiceDidFailToLoadMessages() {

    }

    // MARK: DaysUntilConventionServiceObserver

    func conventionCountdownStateDidChange(to state: ConventionCountdownState) {
        switch state {
        case .countingDown(let daysRemaining):
            daysUntilConvention = daysRemaining

        case .countdownElapsed:
            daysUntilConvention = nil
        }

        regenerateViewModel()
    }

    // MARK: EventsServiceObserver

    func eurofurenceApplicationDidUpdateRunningEvents(to events: [Event2]) {
        runningEvents = events
        regenerateViewModel()
    }

    func eurofurenceApplicationDidUpdateUpcomingEvents(to events: [Event2]) {
        upcomingEvents = events
        regenerateViewModel()
    }

    // MARK: Private

    private func regenerateViewModel() {
        let userWidgetViewModel = makeUserWidgetViewModel()
        announcementsService.fetchAnnouncements { (announcements) in
            var components = [NewsViewModelComponent]()
            components.append(UserComponent(viewModel: userWidgetViewModel))

            if let daysUntilConvention = self.daysUntilConvention {
                components.append(CountdownComponent(daysUntilConvention: daysUntilConvention))
            }

            components.append(AnnouncementsComponent(announcements: announcements))

            if self.daysUntilConvention == nil {
                if !self.upcomingEvents.isEmpty {
                    components.append(EventsComponent(title: .upcomingEvents, events: self.upcomingEvents, relativeTimeFormatter: self.relativeTimeIntervalCountdownFormatter))
                }

                if !self.runningEvents.isEmpty {
                    components.append(EventsComponent(title: .runningEvents, events: self.runningEvents, relativeTimeFormatter: self.relativeTimeIntervalCountdownFormatter))
                }
            }

            let viewModel = ViewModel(components: components)
            self.delegate?.viewModelDidUpdate(viewModel)
        }
{'fraction_non_alphanumeric': 0.06163257852447042, 'fraction_numerical': 0.00310445580715851, 'mean_word_length': 2.7952182952182953, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7486637', 'n_tokens_mistral': 2640, 'n_tokens_neox': 2436, 'n_words': 514}