<commit_before>//
//  AuthenticationController.swift
//  VimeoNetworkingExample-iOS
//
//  Created by <NAME> on 3/21/16.
//  Copyright © 2016 Vimeo. All rights reserved.
//

import Foundation

final class AuthenticationController
{
    private static let ErrorDomain = "AuthenticationControllerErrorDomain"
    
    private static let ErrorAuthToken = <PASSWORD> // TODO: Make this an enum to ensure uniqueness [RH] (3/23/16)
    
    typealias AuthenticationCompletion = ResultCompletion<VIMAccountNew>.T
    
    let configuration: AppConfiguration
    let client: VimeoClient
    
    let accountStore = AccountStore()
    
    init(configuration: AppConfiguration, client: VimeoClient)
    {
        self.configuration = configuration
        self.client = client
    }
    
    // MARK: - 
    
    /// This method will:
    /// 1. check for a user authenticated account, then 
    /// 2. check for a client credentials authenticated account, then finally
    /// 3. attempt to authenticate with client credentials
    func initialAuthentication(completion: AuthenticationCompletion)
    {
        let userAccount: VIMAccountNew?
        let clientCredentialsAccount: VIMAccountNew?
        
        // check saved accounts
        do
        {
            userAccount = try self.accountStore.loadAccount(.User)
            clientCredentialsAccount = try self.accountStore.loadAccount(.ClientCredentials)
            
            if let account = userAccount ?? clientCredentialsAccount
            {
                try self.setupRequestSerializer(account: account)
                
                completion(result: .Success(result: account))
                
                return
            }
        }
        catch let error
        {
            completion(result: .Failure(error: error as NSError))
        }
        
        // if necessary, make a request for client credentials
        
        self.clientCredentialsGrant(completion)
    }
    
    // MARK: -
    
    func clientCredentialsGrant(completion: AuthenticationCompletion)
    {
        let request = AuthenticationRequest.postClientCredentialsGrant(scopes: self.configuration.scopes)
        
        self.authenticate(request: request, completion: completion)
    }
    
    func codeGrant()
    {
        // TODO:  [RH] (3/23/16)
    }
    
    func login(username username: String, password: String, completion: AuthenticationCompletion)
    {
        let request = AuthenticationRequest.postLogin(username: username, password: password, scopes: self.configuration.scopes)
        
        self.authenticate(request: request, completion: completion)
    }
    
    func join(name name: String, email: String, password: String, completion: AuthenticationCompletion)
    {
        let request = AuthenticationRequest.postJoin(name: name, email: email, password: password, scopes: self.configuration.scopes)
        
        self.authenticate(request: request, completion: completion)
    }
    
    func facebookLogin()
    {
        // TODO:  [RH] (3/23/16)
    }
    
    func facebookJoin()
    {
        // TODO:  [RH] (3/23/16)
    }
    
    private func authenticate(request request: AuthenticationRequest, completion: AuthenticationCompletion)
    {
        self.client.request(request) { result in
            
            let handledResult = self.handleAuthenticationResult(result)
            
            completion(result: handledResult)
        }
    }
    
    private func handleAuthenticationResult(result: Result<VIMAccountNew>) -> Result<VIMAccountNew>
    {
        guard case .Success(let account) = result
        else
        {
            // An error was returned from the API, there's nothing to handle [RH]
            
            return result
        }
        
        do
        {
            try self.setupRequestSerializer(account: account)
            
            let accountType: AccountStore.AccountType = (account.user != nil) ? .User : .ClientCredentials
            try self.accountStore.saveAccount(account, type: accountType)<commit_msg>authentication methods<commit_after>//
//  AuthenticationController.swift
//  VimeoNetworkingExample-iOS
//
//  Created by <NAME> on 3/21/16.
//  Copyright © 2016 Vimeo. All rights reserved.
//

import Foundation

final class AuthenticationController
{
    private static let ErrorDomain = "AuthenticationControllerErrorDomain"
    
    private static let ErrorAuthToken = <PASSWORD> // TODO: Make this an enum to ensure uniqueness [RH] (3/23/16)
    
    typealias AuthenticationCompletion = ResultCompletion<VIMAccountNew>.T
    
    let configuration: AppConfiguration
    let client: VimeoClient
    
    let accountStore = AccountStore()
    
    init(configuration: AppConfiguration, client: VimeoClient)
    {
        self.configuration = configuration
        self.client = client
    }
    
    // MARK: - Launch
    
    /// This method will:
    /// 1. check for a user authenticated account, then 
    /// 2. check for a client credentials authenticated account, then finally
    /// 3. attempt to authenticate with client credentials
    func initialAuthentication(completion: AuthenticationCompletion)
    {
        let userAccount: VIMAccountNew?
        let clientCredentialsAccount: VIMAccountNew?
        
        // check saved accounts
        do
        {
            userAccount = try self.accountStore.loadAccount(.User)
            clientCredentialsAccount = try self.accountStore.loadAccount(.ClientCredentials)
            
            if let account = userAccount ?? clientCredentialsAccount
            {
                try self.setupRequestSerializer(account: account)
                
                completion(result: .Success(result: account))
                
                return
            }
        }
        catch let error
        {
            completion(result: .Failure(error: error as NSError))
        }
        
        // if necessary, make a request for client credentials
        
        self.clientCredentialsGrant(completion)
    }
    
    // MARK: - Public Authentication
    
    func clientCredentialsGrant(completion: AuthenticationCompletion)
    {
        let request = AuthenticationRequest.postClientCredentialsGrant(scopes: self.configuration.scopes)
        
        self.authenticate(request: request, completion: completion)
    }
    
    func codeGrant(code code: String, redirectURI: String, completion: AuthenticationCompletion)
    {
        let request = AuthenticationRequest.postCodeGrant(code: code, redirectURI: redirectURI)
        
        self.authenticate(request: request, completion: completion)
    }
    
    // MARK: - Private Authentication
    
    func login(username username: String, password: String, completion: AuthenticationCompletion)
    {
        let request = AuthenticationRequest.postLogin(username: username, password: password, scopes: self.configuration.scopes)
        
        self.authenticate(request: request, completion: completion)
    }
    
    func join(name name: String, email: String, password: String, completion: AuthenticationCompletion)
    {
        let request = AuthenticationRequest.postJoin(name: name, email: email, password: password, scopes: self.configuration.scopes)
        
        self.authenticate(request: request, completion: completion)
    }
    
    func facebookLogin(facebookToken facebookToken: String, completion: AuthenticationCompletion)
    {
        let request = AuthenticationRequest.postLoginFacebook(facebookToken: facebookToken, scopes: self.configuration.scopes)
        
        self.authenticate(request: request, completion: completion)
    }
    
    func facebookJoin(facebookToken facebookToken: String, completion: AuthenticationCompletion)
    {
        let request = AuthenticationRequest.postJoinFacebook(facebookToken: facebookToken, scopes: self.configuration.scopes)
        
        self.authenticate(request: request, completion: completion)
    }
    
    // MARK: - Private
    
    private func authenticate(request request: AuthenticationRequest, completion: AuthenticationCompletion)
    {
        self.client.request(request) { result in
            
            let handledResult = self.handleAuthenticationResult(result)
            
            completion(result: handledResult)
        }
    }
    
    private func handleAuthenticationResult(result: Result<VIMAccountNew>) -> Result<VIMAccountNew>
    {
        guard case .Success(let account) = result
        else
        {
            // An error was returned from the API, there's nothing to handle [RH]
            
            return result
        }
        
        do
        {
            try self.setupRequestSerializer(account: account)
            
            let accountType: AccountStore.AccountType = (account.user != nil) ? .User : .ClientCredentials
            try self.accountStore.saveAccount(account, type: accountType)
{'fraction_non_alphanumeric': 0.07620006713662303, 'fraction_numerical': 0.005482824213942038, 'mean_word_length': 2.2981549815498155, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6262725', 'n_tokens_mistral': 2270, 'n_tokens_neox': 2163, 'n_words': 569}