<commit_before>//
//  SYWireframe.swift
//  SYArtisanFrame
//
//  Created by <NAME> on 12/21/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import UIKit

public typealias SYWireframeCompletionHandler = () -> Void
public typealias SYWireframeViewControllerBuilder = (params: Dictionary<String, AnyObject>) -> UIViewController
public typealias SYWireframeViewControllerNavigator = (fromViewController: UIViewController, toViewController: UIViewController, completionHandler: SYWireframeCompletionHandler) -> Void

/**
 Wireframe deal with all the view controller initialization, configuration, navigation, transition etc. works.
 
 The basic wireframe rules are configured in the .plist file. 
 A classic navigation flow from view controller <X> to <Y> will be like this:
 
    - wireframe look up configuration map for X with Port and Gate(optional), result Y
    - wireframe initialize Y with relevant builder and params
    - wireframe use relevant navigator to do the presentation from X to Y
 
 
 The Port and Gate are simply string combinations to identiy a navigation for a given view controller,
 for example:
 if view controller X has three navigation point to three different view controllers
 you can define X-Next-A, X-Next-B, X-Next-C or X-List, X-Detail, X-Setting for them, the rules are up to you.
 But for a convenience and ease of use, it will be good to follow some certain rules when you define them.
 The X is the Code you give to the view controller for short, remember to assign the real class name for it in the .plist setting file (section Decodes), so that the wireframe can find the right code for current navigating view controller automatically.
 
 
 There are two ways for wirefirm initialize a view controller:
    1. by storyboard, you can set the storyboard file name and the view controller's id in the .plist file
    2. by code, you can assign a builder name in .plist file, also register that builder to wirefirm by code
 Further more, if you want to configure your new view controllers, please subclass wireframe and override  `configureViewController:fromViewController:withParams:`
 
 
 You can pick any presentation effect as you want for each navigation, assing the navigator name in the .plist file and register the navigator to wirefirm for specific method, the libaray already set up a default navigator set for quick start.
 You can also set a transition apparatus for more customized transition animations.
 
*/
public class SYWireframe {
    public static let defaultWireframe = SYWireframe(plistFileName: defaultPropertyListFileName)
    
    private let codes: Dictionary<String, String>
    private let decodes: Dictionary<String, Dictionary<String, String>>
    private let destinations: Dictionary<String, Dictionary<String, String>>
    // view controller builders map: builderName -> builder
    private var builders: Dictionary<String, SYWireframeViewControllerBuilder>
    // view controller navigators map: navigatorName -> navigator
    private var navigators: Dictionary<String, SYWireframeViewControllerNavigator>
    
    public var transitionApparatus: SYWireframeTransitionApparatus?
    
    public init(plistFileName: String) {
        let path = NSBundle(forClass: self.dynamicType).pathForResource(plistFileName, ofType: "plist")
        let plist = NSDictionary(contentsOfFile: path!)!
        decodes = plist["Decodes"] as! Dictionary<String, Dictionary<String, String>>
        destinations = plist["Destinations"] as! Dictionary<String, Dictionary<String, String>>
        var codes = [String: String]()
        for (code, properties) in decodes {
            if let className = properties["class"] {
                codes.updateValue(className, forKey: code)
            }
        }
        self.codes = codes
        builders = [String: SYWireframeViewControllerBuilder]()
        navigators = [String: SYWireframeViewControllerNavigator]()
    }
    
    public class func setDefaultPlistFileName(name: String) {
        defaultPropertyListFileName = name
    }
    
    
    // MARK: Registration
    
    public func registerViewControllerBuilder(builder: SYWireframeViewControllerBuilder, forName builderName: String) {
        builders.updateValue(builder, forKey: builderName)
    }
    
    public func registerViewControllerNavigator(navigator: SYWireframeViewControllerNavigator, forName navigatorName: String) {
        navigators.updateValue(navigator, forKey: navigatorName)
    }
    
    // MARK: Configuration
    
    /**
    Override this method to setup your own configuration logic
    DO call super() while you override the method if you want reuse the transition setup flow
    
    - parameter toViewController:   the view controller to be configured, i.e. the destination controller
    - parameter fromViewController: the from view controller which present the configured controller
    - parameter withParams:         parameters
    */
    public func configureViewController(toViewController: UIViewController, fromViewController: UIViewController, withParams: Dictionary<String, AnyObject>) {
        if let transition = transitionApparatus {
            if toViewController is UINavigationController {
                transition.setupTransitionForNavigationController(toViewController as! UINavigationController)
            }
            transition.setupTransitionFromViewController(fromViewController, toViewController: toViewController)
        }<commit_msg>add default builders and navigators<commit_after>//
//  SYWireframe.swift
//  SYArtisanFrame
//
//  Created by <NAME> on 12/21/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import UIKit

public typealias SYWireframeCompletionHandler = () -> Void
public typealias SYWireframeViewControllerBuilder = (params: Dictionary<String, AnyObject>) -> UIViewController
public typealias SYWireframeViewControllerNavigator = (fromViewController: UIViewController, toViewController: UIViewController, completionHandler: SYWireframeCompletionHandler) -> Void

/**
 Wireframe deal with all the view controller initialization, configuration, navigation, transition etc. works.
 
 The basic wireframe rules are configured in the .plist file. 
 A classic navigation flow from view controller <X> to <Y> will be like this:
 
    - wireframe look up configuration map for X with Port and Gate(optional), result Y
    - wireframe initialize Y with relevant builder and params
    - wireframe use relevant navigator to do the presentation from X to Y
 
 
 The Port and Gate are simply string combinations to identiy a navigation for a given view controller,
 for example:
 if view controller X has three navigation point to three different view controllers
 you can define X-Next-A, X-Next-B, X-Next-C or X-List, X-Detail, X-Setting for them, the rules are up to you.
 But for a convenience and ease of use, it will be good to follow some certain rules when you define them.
 The X is the Code you give to the view controller for short, remember to assign the real class name for it in the .plist setting file (section Decodes), so that the wireframe can find the right code for current navigating view controller automatically.
 
 
 There are two ways for wirefirm initialize a view controller:
    1. by storyboard, you can set the storyboard file name and the view controller's id in the .plist file
    2. by code, you can assign a builder name in .plist file, also register that builder to wirefirm by code
 Further more, if you want to configure your new view controllers, please subclass wireframe and override  `configureViewController:fromViewController:withParams:`
 
 
 You can pick any presentation effect as you want for each navigation, assing the navigator name in the .plist file and register the navigator to wirefirm for specific method, the libaray already set up a default navigator set for quick start.
 You can also set a transition apparatus for more customized transition animations.
 
*/
public class SYWireframe {
    public static let defaultWireframe = SYWireframe(plistFileName: defaultPropertyListFileName)
    
    private let codes: Dictionary<String, String>
    private let decodes: Dictionary<String, Dictionary<String, String>>
    private let destinations: Dictionary<String, Dictionary<String, String>>
    // view controller builders map: builderName -> builder
    private var builders: Dictionary<String, SYWireframeViewControllerBuilder>
    // view controller navigators map: navigatorName -> navigator
    private var navigators: Dictionary<String, SYWireframeViewControllerNavigator>
    
    public var transitionApparatus: SYWireframeTransitionApparatus?
    
    public init(plistFileName: String) {
        let path = NSBundle(forClass: self.dynamicType).pathForResource(plistFileName, ofType: "plist")
        let plist = NSDictionary(contentsOfFile: path!)!
        decodes = plist["Decodes"] as! Dictionary<String, Dictionary<String, String>>
        destinations = plist["Destinations"] as! Dictionary<String, Dictionary<String, String>>
        var codes = [String: String]()
        for (code, properties) in decodes {
            if let className = properties["class"] {
                codes.updateValue(className, forKey: code)
            }
        }
        self.codes = codes
        builders = [String: SYWireframeViewControllerBuilder]()
        navigators = [String: SYWireframeViewControllerNavigator]()
    }
    
    public class func setDefaultPlistFileName(name: String) {
        defaultPropertyListFileName = name
    }
    
    
    // MARK: Registration
    
    public func registerViewControllerBuilder(builder: SYWireframeViewControllerBuilder, forName builderName: String) {
        builders.updateValue(builder, forKey: builderName)
    }
    
    /**
     Default Builder list:
        - UIAlertController
     */
    public func registerDefaultBuilders() {
        registerViewControllerBuilder({ (params) -> UIViewController in
            let alertController = UIAlertController(title: params["title"] as? String, message: params["message"] as? String, preferredStyle: .Alert)
            if let actions = params["actions"] as? [UIAlertAction] {
                for action in actions {
                    alertController.addAction(action)
                }
            }
            if let color = params["color"] as? UIColor {
                alertController.view.tintColor = color
            }
            return alertController
        }, forName: "alert")
    }
    
    public func registerViewControllerNavigator(navigator: SYWireframeViewControllerNavigator, forName navigatorName: String) {
        navigators.updateValue(navigator, forKey: navigatorName)
    }
    
    /**
     Default Navigator list:
        - animated-present (animated == true)
        - instant-present (animated == false)
        - animated-dismiss
        - instand-dismiss
        - animated-push
        - animated-pop
        - animated-pop-root
     */
    public func registerDefaultNavigators() {
        registerViewControllerNavigator({ (fromViewController, toViewController, completionHandler) -> Void in
            fromViewController.presentViewController(toViewController, animated: true, completion: completionHandler)
            }, forName: "animated-present")
        registerViewControllerNavigator({ (fromViewController, toViewController, completionHandler) -> Void in
            fromViewController.presentViewController(toViewController, animated: false, completion: completionHandler)
            }, forName: "instant-present")
        registerViewControllerNavigator({ (fromViewController, toViewController, completionHandler) -> Void in
            fromViewController.dismissViewControllerAnimated(true, completion: completionHandler)
            }, forName: "animated-dismiss")
        registerViewControllerNavigator({ (fromViewController, toViewController, completionHandler) -> Void in
            fromViewController.dismissViewControllerAnimated(false, completion: completionHandler)
            }, forName: "instant-dismiss")
        registerViewControllerNavigator({ (fromViewController, toViewController, completionHandler) -> Void in
            fromViewController.navigationController?.pushViewController(toViewController, animated: true)
            completionHandler()
            }, forName: "animated-push")
        registerViewControllerNavigator({ (fromViewController, toViewController, completionHandler) -> Void in
            fromViewController.navigationController?.popViewControllerAnimated(true)
            completionHandler()
            }, forName: "animated-pop")
        registerViewControllerNavigator({ (fromViewController, toViewController, completionHandler) -> Void in
            fromViewController.navigationController?.popToRootViewControllerAnimated(true)
            completionHandler()
            }, forName: "animated-pop-root")
    }
    
    // MARK: Configuration
    
    /**
    Override this method to setup your own configuration logic
    DO call super() while you override the method if you want reuse the transition setup flow
    
    - parameter toViewController:   the view controller to be configured, i.e. the destination controller
    - parameter fromViewController: the from view controller which present the configured controller
    - parameter withParams:         parameters
    */
    public func configureViewController(toViewController: UIViewController, fromViewController: UIViewController, withParams: Dictionary<String, AnyObject>) {
        if let transition = transitionApparatus {
            if toViewController is UINavigationController {
                transition.setupTransitionForNavigationController(toViewController as! UINavigationController)
            }
            transition.setupTransitionFromViewController(fromViewController, toViewController: toViewController)
        }
{'fraction_non_alphanumeric': 0.06498921639108556, 'fraction_numerical': 0.0017253774263120058, 'mean_word_length': 3.5880606860158313, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 55, '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': '4925502', 'n_tokens_mistral': 3382, 'n_tokens_neox': 3123, 'n_words': 1243}