<commit_before>//
//  TweetPresenter.swift
//  MeetupTweet
//
//  Created by <NAME> on 2016/03/03.
//  Copyright © 2016年 <NAME>. All rights reserved.
//

import Foundation
import RxSwift
import AppKit
import OAuthSwift
import TwitterAPI

class NicoNicoCommentFlowWindowDataSource: FlowWindowDataSource {

    var subscription: Disposable?
    fileprivate let tweetSearchUseCase: TwitterStraemAPIUseCase
    fileprivate let disposeBag = DisposeBag()
    fileprivate var comments: [String: (comment: CommentType, view: CommentView)] = [:]
    fileprivate var commentViews: [CommentView?] = []
    fileprivate var window: NSWindow?

    init(oauthClient: OAuthClient) {
        self.tweetSearchUseCase = TwitterStraemAPIUseCase(oauthClient: oauthClient)
    }

    func search(_ search: String, screen: NSScreen) {
        refreshComments()
        window = makeTweetWindow(screen)

        let tweetStream = tweetSearchUseCase.startStream(search)
            .observeOn(MainScheduler.instance)
            .startWith(Announce(search: search))
            .filter { !$0.message.hasPrefix("RT") }

        subscription = Observable.of(tweetStream, AnnounceUseCase.intervalTextStream(search))
            .merge()
            .subscribe(onNext: {  [unowned self] comment in
                self.addComment(comment)
            })
        
        subscription?.disposed(by: disposeBag)
    }
    
    func stop() {
        window?.orderOut(nil)
        refreshComments()
    }
}

private extension NicoNicoCommentFlowWindowDataSource {

    func refreshComments() {
        tweetSearchUseCase.stopStream()
        subscription?.dispose()
        comments = [:]
        commentViews = []
    }
    
    func addComment(_ comment: CommentType) {
        guard let window = window else { return }

        let view = makeCommentView(comment, from: window)
        
        window.contentView?.addSubview(view)
        comments[comment.identifier] = (comment: comment, view: view)

        startAnimationComment(comment, view: view)
    }
    
    func removeComment(_ comment: CommentType) {
        if let tweet = comments[comment.identifier] {
            tweet.view.removeFromSuperview()
            comments[comment.identifier] = nil
        }
    }
    
    func startAnimationComment(_ comment: CommentType, view: CommentView) {
        guard let window = window else { return }

        // TextFieldの移動開始
        let windowFrame = window.frame
        
        let v: CGFloat = 200.0

        let firstDuration = TimeInterval(view.frame.width / v)

        let len = windowFrame.width
        let secondDuration = TimeInterval(len / v)

        NSAnimationContext.runAnimationGroup(
            { context in
                context.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
                context.duration = firstDuration
                view.animator().frame = view.frame.offsetBy(dx: -view.frame.width, dy: 0)

            }, completionHandler: { [weak self] in

                guard let `self` = self else { return }

                for (index, v) in self.commentViews.enumerated() {
                    if v == view {
                        self.commentViews[index] = nil
                        break;
                    }
                }

                NSAnimationContext.runAnimationGroup({ context in
                        context.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
                        context.duration = secondDuration
                        view.animator().frame = view.frame.offsetBy(dx: -len, dy: 0)
                        
                    }, completionHandler: { [weak self] in
                        self?.removeComment(comment)
                })
            }
        )
    }
    
    func makeCommentView(_ comment: CommentType, from window: NSWindow) -> CommentView {

        let commentView: CommentView
        switch comment.type {<commit_msg>Improve code style.<commit_after>//
//  TweetPresenter.swift
//  MeetupTweet
//
//  Created by <NAME> on 2016/03/03.
//  Copyright © 2016年 <NAME>. All rights reserved.
//

import Foundation
import RxSwift
import AppKit
import OAuthSwift
import TwitterAPI

class NicoNicoCommentFlowWindowDataSource: FlowWindowDataSource {

    var subscription: Disposable?
    fileprivate let tweetSearchUseCase: TwitterStraemAPIUseCase
    fileprivate let disposeBag = DisposeBag()
    fileprivate var comments: [String: (comment: CommentType, view: CommentView)] = [:]
    fileprivate var commentViews: [CommentView?] = []
    fileprivate var window: NSWindow?

    init(oauthClient: OAuthClient) {
        self.tweetSearchUseCase = TwitterStraemAPIUseCase(oauthClient: oauthClient)
    }

    func search(_ search: String, screen: NSScreen) {
        refreshComments()
        window = makeTweetWindow(screen)

        let tweetStream = tweetSearchUseCase.startStream(search)
            .observeOn(MainScheduler.instance)
            .startWith(Announce(search: search))
            .filter { !$0.message.hasPrefix("RT") }

        subscription = Observable.of(tweetStream, AnnounceUseCase.intervalTextStream(search))
            .merge()
            .subscribe(onNext: {  [unowned self] comment in
                self.addComment(comment)
            })
        
        subscription?.disposed(by: disposeBag)
    }
    
    func stop() {
        window?.orderOut(nil)
        refreshComments()
    }
}

private extension NicoNicoCommentFlowWindowDataSource {

    func refreshComments() {
        tweetSearchUseCase.stopStream()
        subscription?.dispose()
        comments = [:]
        commentViews = []
    }
    
    func addComment(_ comment: CommentType) {
        guard let window = window else { return }

        let view = makeCommentView(comment, from: window)
        
        window.contentView?.addSubview(view)
        comments[comment.identifier] = (comment: comment, view: view)

        startAnimationComment(comment, view: view)
    }
    
    func removeComment(_ comment: CommentType) {
        if let tweet = comments[comment.identifier] {
            tweet.view.removeFromSuperview()
            comments[comment.identifier] = nil
        }
    }
    
    func startAnimationComment(_ comment: CommentType, view: CommentView) {
        guard let window = window else { return }

        // TextFieldの移動開始
        let windowFrame = window.frame
        
        let v: CGFloat = 200.0

        let firstDuration = TimeInterval(view.frame.width / v)

        let len = windowFrame.width
        let secondDuration = TimeInterval(len / v)

        NSAnimationContext.runAnimationGroup { context in

            context.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
            context.duration = firstDuration
            view.animator().frame = view.frame.offsetBy(dx: -view.frame.width, dy: 0)

        }, completionHandler: { [weak self] in

            guard let `self` = self else { return }

            for (index, v) in self.commentViews.enumerated() {
                if v == view {
                    self.commentViews[index] = nil
                    break;
                }
            }

            NSAnimationContext.runAnimationGroup({ context in
                    context.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
                    context.duration = secondDuration
                    view.animator().frame = view.frame.offsetBy(dx: -len, dy: 0)

                }, completionHandler: { [weak self] in
                    self?.removeComment(comment)
            })
        }
    }
    
    func makeCommentView(_ comment: CommentType, from window: NSWindow) -> CommentView {

        let commentView: CommentView
        switch comment.type {
{'fraction_non_alphanumeric': 0.08779800051268906, 'fraction_numerical': 0.004870546013842604, 'mean_word_length': 2.1387771520514884, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, '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': '3634495', 'n_tokens_mistral': 2138, 'n_tokens_neox': 2009, 'n_words': 468}