<commit_before>//
//  Client.swift
//  Rewatch
//
//  Created by <NAME> on 2015-10-15.
//  Copyright © 2015 Perfectly-Cooked. All rights reserved.
//

import UIKit
import SwiftyJSON
import ReactiveCocoa
import KeychainSwift

class Client: NSObject {
    typealias AuthorizationHandler = (String?, ClientError?) -> Void

    enum ClientError: ErrorType {
        case InternalError
    }
    
    struct Show {
        let id: Int
        let name: String
        var episodes: [Episode]? = []
    }
    
    struct Episode {
        let id: Int
        let title: String
    }
    
    let key: String
    let secret: String
    let session: NSURLSession
    var token: String?
    
    private var authorizationCompletion: AuthorizationHandler?
    
    init(key: String, secret: String, token: String? = nil) {
        self.key = key
        self.secret = secret
        self.token = token
        
        self.session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue())
    }
    
    func authorize(completion: AuthorizationHandler) {
        guard let comps = NSURLComponents(string: "https://www.betaseries.com/authorize") else { return }
        self.authorizationCompletion = completion
        
        var items = [NSURLQueryItem]()
        items.append(NSURLQueryItem(name: "client_id", value: key))
        items.append(NSURLQueryItem(name: "redirect_uri", value: "rewatch://oauth/handle"))
        
        comps.queryItems = items
        
        if let url = comps.URL {
            UIApplication.sharedApplication().openURL(url)
        }
    }
    
    func handleURL(url: NSURL) {
        do {
            let code = try extractCodeFromURL(url)
            let params = ["client_id":key, "client_secret":secret, "redirect_uri": "rewatch://oauth/handle", "code": code]
            sendRequestToPath("members/access_token", params: params, method: "POST")
                .observeOn(UIScheduler())
                .map({ (payload) -> String in
                    return payload["token"].stringValue
                })
                .flatMap(.Latest, transform: { (token) -> SignalProducer<(Show, Episode), NSError> in
                    self.token = token
                    return self.fetchShows().flatMap(FlattenStrategy.Merge, transform: { (show) -> SignalProducer<(Show, Episode), NSError> in
                        return combineLatest(SignalProducer<Show, NSError>(value: show), self.fetchEpisodesFromShow(show))
                    })
                })
                .startWithNext({ (results) -> () in
                    print("Show: \(results.0.name) | Episode: \(results.1.title)")
                })
        } catch {
            print("Got error while handling url \(url) : \(error)")
        }
    }
    
    func fetchShows() -> SignalProducer<Show, NSError> {
        return sendRequestToPath("members/infos", params: nil, method: "GET")
            .flatMap(FlattenStrategy.Latest) { (payload) -> SignalProducer<Show, NSError> in
                return SignalProducer<Show, NSError> { sink, disposable in
                    payload["member"]["shows"].arrayValue.forEach({ showNode in
                        let show = Show(id: showNode["id"].intValue, name: showNode["title"].stringValue, episodes: [])
                        sink.sendNext(show)
                    })
                    sink.sendCompleted()
                }
            }
    }<commit_msg>Map tuple into a flattened dictionary for storage<commit_after>//
//  Client.swift
//  Rewatch
//
//  Created by <NAME> on 2015-10-15.
//  Copyright © 2015 Perfectly-Cooked. All rights reserved.
//

import UIKit
import SwiftyJSON
import ReactiveCocoa
import KeychainSwift

class Client: NSObject {
    typealias AuthorizationHandler = (String?, ClientError?) -> Void

    enum ClientError: ErrorType {
        case InternalError
    }
    
    struct Show {
        let id: Int
        let name: String
        var episodes: [Episode]? = []
    }
    
    struct Episode {
        let id: Int
        let title: String
    }
    
    let key: String
    let secret: String
    let session: NSURLSession
    var token: String?
    
    private var authorizationCompletion: AuthorizationHandler?
    
    init(key: String, secret: String, token: String? = nil) {
        self.key = key
        self.secret = secret
        self.token = token
        
        self.session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue())
    }
    
    func authorize(completion: AuthorizationHandler) {
        guard let comps = NSURLComponents(string: "https://www.betaseries.com/authorize") else { return }
        self.authorizationCompletion = completion
        
        var items = [NSURLQueryItem]()
        items.append(NSURLQueryItem(name: "client_id", value: key))
        items.append(NSURLQueryItem(name: "redirect_uri", value: "rewatch://oauth/handle"))
        
        comps.queryItems = items
        
        if let url = comps.URL {
            UIApplication.sharedApplication().openURL(url)
        }
    }
    
    func handleURL(url: NSURL) {
        do {
            let code = try extractCodeFromURL(url)
            let params = ["client_id":key, "client_secret":secret, "redirect_uri": "rewatch://oauth/handle", "code": code]
            sendRequestToPath("members/access_token", params: params, method: "POST")
                .observeOn(UIScheduler())
                .map({ (payload) -> String in
                    return payload["token"].stringValue
                })
                .flatMap(.Latest, transform: { (token) -> SignalProducer<(Show, Episode), NSError> in
                    self.token = token
                    return self.fetchShows().flatMap(FlattenStrategy.Merge, transform: { (show) -> SignalProducer<(Show, Episode), NSError> in
                        return combineLatest(SignalProducer<Show, NSError>(value: show), self.fetchEpisodesFromShow(show))
                    })
                })
                .map({ (show, episode) -> [String: String] in
                    return ["show_id": String(show.id), "show_name": show.name, "episode_id": String(episode.id), "episode_title": episode.title]
                })
                .startWithNext({ (line) -> () in
                    print(line)
                })
        } catch {
            print("Got error while handling url \(url) : \(error)")
        }
    }
    
    func fetchShows() -> SignalProducer<Show, NSError> {
        return sendRequestToPath("members/infos", params: nil, method: "GET")
            .flatMap(FlattenStrategy.Latest) { (payload) -> SignalProducer<Show, NSError> in
                return SignalProducer<Show, NSError> { sink, disposable in
                    payload["member"]["shows"].arrayValue.forEach({ showNode in
                        let show = Show(id: showNode["id"].intValue, name: showNode["title"].stringValue, episodes: [])
                        sink.sendNext(show)
                    })
                    sink.sendCompleted()
                }
            }
    }
{'fraction_non_alphanumeric': 0.11274850549145002, 'fraction_numerical': 0.0036146253301821214, 'mean_word_length': 1.9937578027465668, 'pattern_counts': {'":': 12, '<': 17, '<?xml version=': 0, '>': 32, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1315016', 'n_tokens_mistral': 2034, 'n_tokens_neox': 1934, 'n_words': 457}