<commit_before>//
//  SessionManager.swift
//  FiveCalls
//
//  Created by <NAME> on 12/27/17.
//  Copyright © 2017 5calls. All rights reserved.
//

import Auth0
import PromiseKit

extension Notification.Name {
    static let userProfileChanged = Notification.Name("userProfileChanged")
}

public enum SessionManagerError : Error {
    case failedWrite
    case invalidStatus
    case noAccessToken
    case notLoggedIn
}

class SessionManager {
    
    // Set up our singleton
    static let shared = SessionManager()
    
    // The profile for the user who is currently logged in, or nil if the user isn't logged in
    var userProfile : UserInfo?

    let credentialsManager = CredentialsManager(authentication: Auth0.authentication())
    
    func userHasCredentials() -> Bool {
        return credentialsManager.hasValid()
    }
    
    func userIsLoggedIn() -> Bool {
        return userProfile != nil
    }
    
    func startSession() {
        firstly {
            self.authenticate()
        }.then { credentials -> Promise<UserInfo> in
            guard self.credentialsManager.store(credentials: credentials) else {
                print("Error writing the user's credentials")
                return Promise(error: SessionManagerError.failedWrite)
            }
            return self.fetchUserProfile(credentials)
        }.then { userInfo -> Promise<Bool> in
            self.userProfile = userInfo
            return self.sendUnreportedStats()
        }.done { _ in
            NotificationCenter.default.post(Notification(name: .userProfileChanged))
        }.catch { error in
            print("Failed to start a user session: \(error)")
        }
    }
    
    func stopSession() {
        let credentialsManager = CredentialsManager(authentication: Auth0.authentication())
        if (!credentialsManager.clear()) {
            print("Error clearing user credentials")
        }
        userProfile = nil
        NotificationCenter.default.post(Notification(name: .userProfileChanged))
    }

    private func authenticate() -> Promise<Credentials> {
        return Promise { seal in
            guard credentialsManager.hasValid() else {
                // No valid credentials exist, present the hosted login page
                Auth0
                    .webAuth()
                    .audience("https://5callsos.auth0.com/userinfo")
                    .scope("openid profile offline_access")
                    .start { result in
                        switch result {
                        case .success(let credentials):
                            seal.fulfill(credentials)
                        case .failure(let error):
                            print("User login failed with error: \(error)")
                            seal.reject(error)<commit_msg>log error in crashlytics when sessions fail<commit_after>//
//  SessionManager.swift
//  FiveCalls
//
//  Created by <NAME> on 12/27/17.
//  Copyright © 2017 5calls. All rights reserved.
//

import Auth0
import PromiseKit
import Crashlytics

extension Notification.Name {
    static let userProfileChanged = Notification.Name("userProfileChanged")
}

public enum SessionManagerError : Error {
    case failedWrite
    case invalidStatus
    case noAccessToken
    case notLoggedIn
}

class SessionManager {
    
    // Set up our singleton
    static let shared = SessionManager()
    
    // The profile for the user who is currently logged in, or nil if the user isn't logged in
    var userProfile : UserInfo?

    let credentialsManager = CredentialsManager(authentication: Auth0.authentication())
    
    func userHasCredentials() -> Bool {
        return credentialsManager.hasValid()
    }
    
    func userIsLoggedIn() -> Bool {
        return userProfile != nil
    }
    
    func startSession() {
        firstly {
            self.authenticate()
        }.then { credentials -> Promise<UserInfo> in
            guard self.credentialsManager.store(credentials: credentials) else {
                print("Error writing the user's credentials")
                return Promise(error: SessionManagerError.failedWrite)
            }
            return self.fetchUserProfile(credentials)
        }.then { userInfo -> Promise<Bool> in
            self.userProfile = userInfo
            return self.sendUnreportedStats()
        }.done { _ in
            NotificationCenter.default.post(Notification(name: .userProfileChanged))
        }.catch { error in
            print("Failed to start a user session: \(error)")
            Crashlytics.sharedInstance().recordError(error, withAdditionalUserInfo: ["message" : "Error starting session"])
        }
    }
    
    func stopSession() {
        let credentialsManager = CredentialsManager(authentication: Auth0.authentication())
        if (!credentialsManager.clear()) {
            print("Error clearing user credentials")
        }
        userProfile = nil
        NotificationCenter.default.post(Notification(name: .userProfileChanged))
    }

    private func authenticate() -> Promise<Credentials> {
        return Promise { seal in
            guard credentialsManager.hasValid() else {
                // No valid credentials exist, present the hosted login page
                Auth0
                    .webAuth()
                    .audience("https://5callsos.auth0.com/userinfo")
                    .scope("openid profile offline_access")
                    .start { result in
                        switch result {
                        case .success(let credentials):
                            seal.fulfill(credentials)
                        case .failure(let error):
                            print("User login failed with error: \(error)")
                            seal.reject(error)
{'fraction_non_alphanumeric': 0.08372334893395736, 'fraction_numerical': 0.005893569076096377, 'mean_word_length': 1.9681069958847737, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 21, 'https://': 2, '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': '7136622', 'n_tokens_mistral': 1440, 'n_tokens_neox': 1362, 'n_words': 389}