text:
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotifier.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IObserver.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IMediator.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotifier.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IObserver.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * A base IObserver implementation.
    *
    * In PureMVC, the Observer class assumes these responsibilities:
    *

    *
Encapsulate the notification (callback) method of the interested object.
    *
Encapsulate the notification context (this) of the interested object.
    *
Provide methods for setting the interested object notification method and context.
    *
Provide a method for notifying the interested object.
    *
    * PureMVC does not rely upon underlying event models such as the one provided in JavaScript DOM API,
    * and TypeScript does not have an inherent event model.
    *
    * The Observer Pattern as implemented within PureMVC exists to support event driven
    * communication between the application and the actors of the MVC triad (Model, View, Controller).
    *
    * An Observer is an object that encapsulates information about an interested object with a
    * notification method that should be called when an INotification is broadcast.
    * The Observer then acts as a proxy for notifying the interested object.
    *
    * Observers can receive Notifications by having their notifyObserver
    * method invoked, passing in an object implementing the INotification interface,
    * such as a subclass of Notification.
    */
    var Observer = (function () {
        /**
        * Constructs an Observer instance.
        *
        * @param notifyMethod
        * 		The notification method of the interested object.
        *
        * @param notifyContext
        * 		The notification context of the interested object.
        */
        function Observer(notifyMethod, notifyContext) {
            /**
            * The notification method of the interested object.
            */
            this.notify = null;
            /**
            * The notification context of the interested object.
            */
            this.context = null;
            this.setNotifyMethod(notifyMethod);
            this.setNotifyContext(notifyContext);
        }
        /**
        * Get the notification method.
        *
        * @return
        * 		The notification (callback) method of the interested object.
        */
        Observer.prototype.getNotifyMethod = function () {
            return this.notify;
        };

        /**
        * Set the notification method.
        *
        * The notification method should take one parameter of type INotification.
        *
        * @param notifyMethod
        * 		The notification (callback) method of the interested object.
        */
        Observer.prototype.setNotifyMethod = function (notifyMethod) {
            this.notify = notifyMethod;
        };

        /**
        * Get the notification context.
        *
        * @return
        * 		The notification context (this) of the interested object.
        */
        Observer.prototype.getNotifyContext = function () {
            return this.context;
        };

        /**
        * Set the notification context.
        *
        * @param notifyContext
        * 		The notification context (this) of the interested object.
        */
        Observer.prototype.setNotifyContext = function (notifyContext) {
            this.context = notifyContext;
        };

        /**
        * Notify the interested object.
        *
        * @param notification
        * 		The INotification to pass to the interested object's notification
        * 		method.
        */
        Observer.prototype.notifyObserver = function (notification) {
            this.getNotifyMethod().call(this.getNotifyContext(), notification);
        };

        /**
        * Compare an object to the notification context.
        *
        * @param object
        * 		The object to compare.
        *
        * @return
        * 		The object and the notification context are the same.
        */
        Observer.prototype.compareNotifyContext = function (object) {
            return object === this.context;
        };
        return Observer;
    })();
    puremvc.Observer = Observer;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IView.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IObserver.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IMediator.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * The View class for PureMVC.
    *
    * A multiton IView implementation.
    *
    * In PureMVC, the View class assumes these responsibilities:
    *

    *
Maintain a cache of IMediator instances.
    *
Provide methods for registering, retrieving, and removing IMediators.
    *
Notifiying IMediators when they are registered or removed.
    *
Managing the Observer lists for each INotification in the
    * application.
    *
Providing a method for attaching IObservers to an
    * INotification's Observer list.
    *
Providing a method for broadcasting an INotification.
    *
Notifying the IObservers of a given INotification when it
    * broadcasts.
    */
    var View = (function () {
        /**
        * This IView implementation is a multiton, so you should not call the
        * constructor directly, but instead call the static multiton Factory method
        * View.getInstance( key ).
        *
        * @param key
        *		Multiton key for this instance of View.
        *
        * @throws Error
        *		Throws an error if an instance for this multiton key has already been constructed.
        */
        function View(key) {
            /**
            * Mapping of Mediator names to Mediator instances.
            *
            * @protected
            */
            this.mediatorMap = null;
            /**
            * Mapping of Notification names to Observers lists.
            *
            * @protected
            */
            this.observerMap = null;
            /**
            * Multiton key for this View instance.
            *
            * @protected
            */
            this.multitonKey = null;
            if (View.instanceMap[key])
                throw Error(View.MULTITON_MSG);

            View.instanceMap[key] = this;

            this.multitonKey = key;
            this.mediatorMap = {};
            this.observerMap = {};

            this.initializeView();
        }
        /**
        * Initialize the multiton View instance.
        *
        * Called automatically by the constructor. This is the opportunity to initialize the
        * multiton instance in a subclass without overriding the constructor.
        */
        View.prototype.initializeView = function () {
        };

        /**
        * Register an IObserver to be notified of INotifications with a
        * given name.
        *
        * @param notificationName
        * 		The name of the INotifications to notify this IObserver
        * 		of.
        *
        * @param observer
        * 		The IObserver to register.
        */
        View.prototype.registerObserver = function (notificationName, observer) {
            var observers = this.observerMap[notificationName];
            if (observers)
                observers.push(observer);
            else
                this.observerMap[notificationName] = [observer];
        };

        /**
        * Remove a list of IObservers for a given notifyContext from an
        * IObserver list for a given INotification name.
        *
        * @param notificationName
        * 		Which IObserver list to remove from.
        *
        * @param notifyContext
        * 		Remove the IObserver with this object as its
        *		notifyContext.
        */
        View.prototype.removeObserver = function (notificationName, notifyContext) {
            //The observer list for the notification under inspection
            var observers = this.observerMap[notificationName];

            //Find the observer for the notifyContext.
            var i = observers.length;
            while (i--) {
                var observer = observers[i];
                if (observer.compareNotifyContext(notifyContext)) {
                    observers.splice(i, 1);
                    break;
                }
            }

            /*
            * Also, when a Notification's Observer list length falls to zero, delete the
            * notification key from the observer map.
            */
            if (observers.length == 0)
                delete this.observerMap[notificationName];
        };

        /**
        * Notify the IObservers for a particular INotification.
        *
        * All previously attached IObservers for this INotification's
        * list are notified and are passed a reference to the INotification in the
        * order in which they were registered.
        *
        * @param notification
        * 		The INotification to notify IObservers of.
        */
        View.prototype.notifyObservers = function (notification) {
            var notificationName = notification.getName();

            var observersRef = this.observerMap[notificationName];
            if (observersRef) {
                // Copy the array.
                var observers = observersRef.slice(0);
                var len = observers.length;
                for (var i = 0; i < len; i++) {
                    var observer = observers[i];
                    observer.notifyObserver(notification);
                }
            }
        };

        /**
        * Register an IMediator instance with the View.
        *
        * Registers the IMediator so that it can be retrieved by name, and further
        * interrogates the IMediator for its INotification interests.
        *
        * If the IMediator returns any INotification names to be
        * notified about, an Observer is created to encapsulate the
        * IMediator instance's handleNotification method and register
        * it as an Observer for all INotifications the
        * IMediator is interested in.
        *
        * @param mediator
        * 		A reference to an IMediator implementation instance.
        */
        View.prototype.registerMediator = function (mediator) {
            var name = mediator.getMediatorName();

            //Do not allow re-registration (you must removeMediator first).
            if (this.mediatorMap[name])
                return;

            mediator.initializeNotifier(this.multitonKey);

            //Register the Mediator for retrieval by name.
            this.mediatorMap[name] = mediator;

            //Get Notification interests, if any.
            var interests = mediator.listNotificationInterests();
            var len = interests.length;
            if (len > 0) {
                //Create Observer referencing this mediator's handlNotification method.
                var observer = new puremvc.Observer(mediator.handleNotification, mediator);

                for (var i = 0; i < len; i++)
                    this.registerObserver(interests[i], observer);
            }

            //Alert the mediator that it has been registered.
            mediator.onRegister();
        };

        /**
        * Retrieve an IMediator from the View.
        *
        * @param mediatorName
        * 		The name of the IMediator instance to retrieve.
        *
        * @return
        * 		The IMediator instance previously registered with the given
        *		mediatorName or an explicit null if it doesn't exists.
        */
        View.prototype.retrieveMediator = function (mediatorName) {
            //Return a strict null when the mediator doesn't exist
            return this.mediatorMap[mediatorName] || null;
        };

        /**
        * Remove an IMediator from the View.
        *
        * @param mediatorName
        * 		Name of the IMediator instance to be removed.
        *
        * @return
        *		The IMediator that was removed from the View or a
        *		strict null</null> if the Mediator didn't exist.
        */
        View.prototype.removeMediator = function (mediatorName) {
            // Retrieve the named mediator
            var mediator = this.mediatorMap[mediatorName];
            if (!mediator)
                return null;

            //Get Notification interests, if any.
            var interests = mediator.listNotificationInterests();

            //For every notification this mediator is interested in...
            var i = interests.length;
            while (i--)
                this.removeObserver(interests[i], mediator);

            // remove the mediator from the map
            delete this.mediatorMap[mediatorName];

            //Alert the mediator that it has been removed
            mediator.onRemove();

            return mediator;
        };

        /**
        * Check if a IMediator is registered or not.
        *
        * @param mediatorName
        * 		The IMediator name to check whether it is registered.
        *
        * @return
        *		An IMediator is registered with the given mediatorName.
        */
        View.prototype.hasMediator = function (mediatorName) {
            return this.mediatorMap[mediatorName] != null;
        };

        /**
        * View multiton factory method.
        *
        * @param key
        *		The multiton key of the instance of View to create or retrieve.
        *
        * @return
        *		The singleton instance of View.
        */
        View.getInstance = function (key) {
            if (!View.instanceMap[key])
                View.instanceMap[key] = new View(key);

            return View.instanceMap[key];
        };

        /**
        * Remove a View instance.
        *
        * @param key
        * 		Key identifier of View instance to remove.
        */
        View.removeView = function (key) {
            delete View.instanceMap[key];
        };
        View.MULTITON_MSG = "View instance for this multiton key already constructed!";

        View.instanceMap = {};
        return View;
    })();
    puremvc.View = View;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IController.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IView.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/ICommand.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/patterns/observer/Observer.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/core/View.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * The Controller class for PureMVC.
    *
    * A multiton IController implementation.
    *
    * In PureMVC, the Controller class follows the 'Command and Controller' strategy,
    * and assumes these responsibilities:
    *
    *

    *
Remembering which ICommands are intended to handle which
    * INotifications.
    *
Registering itself as an IObserver with the View for each
    * INotification that it has an ICommand mapping for.
    *
Creating a new instance of the proper ICommand to handle a given
    * INotification when notified by the View.
    *
Calling the ICommand's execute method, passing in the
    * INotification.
    *
    * Your application must register ICommands with the Controller.
    *
    * The simplest way is to subclass Facade, and use its
    * initializeController method to add your registrations.
    */
    var Controller = (function () {
        /**
        * Constructs a Controller instance.
        *
        * This IController implementation is a multiton, so you should not call the
        * constructor directly, but instead call the static multiton Factory method
        * Controller.getInstance( key ).
        *
        * @param key
        *		Multiton key for this instance of Controller
        *
        * @throws Error
        * 		Throws an error if an instance for this multiton key has already been constructed.
        */
        function Controller(key) {
            /**
            * Local reference to the View singleton.
            *
            * @protected
            */
            this.view = null;
            /**
            * Mapping of Notification names to Command constructors references.
            *
            * @protected
            */
            this.commandMap = null;
            /**
            * The multiton Key for this Core.
            *
            * @protected
            */
            this.multitonKey = null;
            if (Controller.instanceMap[key])
                throw Error(Controller.MULTITON_MSG);

            Controller.instanceMap[key] = this;

            this.multitonKey = key;
            this.commandMap = {};
            this.initializeController();
        }
        /**
        * Initialize the multiton Controller instance.
        *
        * Called automatically by the constructor.
        *
        * Note that if you are using a subclass of View in your application, you
        * should also subclass Controller and override the
        * initializeController method in the following way:
        *
        *

        *		// Ensure that the Controller is talking to my IView implementation.
        *		initializeController():void
        *		{
        *			this.view = MyView.getInstance( this.multitonKey );
        *		}
        *

        *
        * @protected
        */
        Controller.prototype.initializeController = function () {
            this.view = puremvc.View.getInstance(this.multitonKey);
        };

        /**
        * If an ICommand has previously been registered to handle the given
        * INotification, then it is executed.
        *
        * @param notification
        * 		The INotification the command will receive as parameter.
        */
        Controller.prototype.executeCommand = function (notification) {
            /*
            * Typed any here instead of Function ( won't compile if set to Function
            * because today the compiler consider that Function is not newable and
            * doesn't have a Class type)
            */
            var commandClassRef = this.commandMap[notification.getName()];
            if (commandClassRef) {
                var command = new commandClassRef();
                command.initializeNotifier(this.multitonKey);
                command.execute(notification);
            }
        };

        /**
        * Register a particular ICommand class as the handler for a particular
        * INotification.
        *
        * If an ICommand has already been registered to handle
        * INotifications with this name, it is no longer used, the new
        * ICommand is used instead.
        *
        * The Observer for the new ICommand is only created if this is
        * the first time an ICommand has been registered for this
        * Notification name.
        *
        * @param notificationName
        * 		The name of the INotification.
        *
        * @param commandClassRef
        * 		The constructor of the ICommand.
        */
        Controller.prototype.registerCommand = function (notificationName, commandClassRef) {
            if (!this.commandMap[notificationName])
                this.view.registerObserver(notificationName, new puremvc.Observer(this.executeCommand, this));

            this.commandMap[notificationName] = commandClassRef;
        };

        /**
        * Check if an ICommand is registered for a given Notification.
        *
        * @param notificationName
        * 		Name of the Notification to check wheter an ICommand is
        * 		registered for.
        *
        * @return
        * 		An ICommand is currently registered for the given
        * 		notificationName.
        */
        Controller.prototype.hasCommand = function (notificationName) {
            return this.commandMap[notificationName] != null;
        };

        /**
        * Remove a previously registered ICommand to INotification
        * mapping.
        *
        * @param notificationName
        * 		The name of the INotification to remove the ICommand
        * 		mapping for.
        */
        Controller.prototype.removeCommand = function (notificationName) {
            // if the Command is registered...
            if (this.hasCommand(notificationName)) {
                this.view.removeObserver(notificationName, this);
                delete this.commandMap[notificationName];
            }
        };

        /**
        * Controller multiton factory method.
        *
        * @param key
        *		The multiton key of the instance of Controller to create or retrieve.
        *
        * @return
        * 		The multiton instance of Controller
        */
        Controller.getInstance = function (key) {
            if (!Controller.instanceMap[key])
                Controller.instanceMap[key] = new Controller(key);

            return Controller.instanceMap[key];
        };

        /**
        * Remove a Controller instance.
        *
        * @param key
        *		Multiton key of the Controller instance to remove.
        */
        Controller.removeController = function (key) {
            delete Controller.instanceMap[key];
        };
        Controller.MULTITON_MSG = "Controller instance for this multiton key already constructed!";

        Controller.instanceMap = {};
        return Controller;
    })();
    puremvc.Controller = Controller;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotifier.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IProxy.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IModel.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IProxy.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * The Model class for PureMVC.
    *
    * A multiton IModel implementation.
    *
    * In PureMVC, the IModel class provides access to model objects
    * Proxies by named lookup.
    *
    * The Model assumes these responsibilities:
    *

    *
Maintain a cache of IProxy instances.
    *
Provide methods for registering, retrieving, and removing Proxy instances.
    *
    * Your application must register IProxy instances with the Model.
    * Typically, you use an ICommand to create and register Proxy instances
    * once the Facade has initialized the core actors.
    */
    var Model = (function () {
        /**
        * This IModel implementation is a multiton, so you should not call the
        * constructor directly, but instead call the static multiton Factory method
        * Model.getInstance( key ).
        *
        * @param key
        *		Multiton key for this instance of Model.
        *
        * @throws Error
        * 		Throws an error if an instance for this multiton key has already been constructed.
        */
        function Model(key) {
            /**
            * HashTable of IProxy registered with the Model.
            *
            * @protected
            */
            this.proxyMap = null;
            /**
            * The multiton key for this core.
            *
            * @protected
            */
            this.multitonKey = null;
            if (Model.instanceMap[key])
                throw Error(Model.MULTITON_MSG);

            Model.instanceMap[key] = this;
            this.multitonKey = key;
            this.proxyMap = {};

            this.initializeModel();
        }
        /**
        * Initialize the multiton Model instance.
        *
        * Called automatically by the constructor. This is the opportunity to initialize the
        * multiton instance in a subclass without overriding the constructor.
        *
        * @protected
        */
        Model.prototype.initializeModel = function () {
        };

        /**
        * Register an IProxy with the Model.
        *
        * @param proxy
        *		An IProxy to be held by the Model.
        */
        Model.prototype.registerProxy = function (proxy) {
            proxy.initializeNotifier(this.multitonKey);
            this.proxyMap[proxy.getProxyName()] = proxy;
            proxy.onRegister();
        };

        /**
        * Remove an IProxy from the Model.
        *
        * @param proxyName
        *		The name of the Proxy instance to be removed.
        *
        * @return
        *		The IProxy that was removed from the Model or an
        *		explicit null</null> if the IProxy didn't exist.
        */
        Model.prototype.removeProxy = function (proxyName) {
            var proxy = this.proxyMap[proxyName];
            if (proxy) {
                delete this.proxyMap[proxyName];
                proxy.onRemove();
            }

            return proxy;
        };

        /**
        * Retrieve an IProxy from the Model.
        *
        * @param proxyName
        *		 The IProxy name to retrieve from the Model.
        *
        * @return
        *		The IProxy instance previously registered with the given
        *		proxyName or an explicit null if it doesn't exists.
        */
        Model.prototype.retrieveProxy = function (proxyName) {
            //Return a strict null when the proxy doesn't exist
            return this.proxyMap[proxyName] || null;
        };

        /**
        * Check if an IProxy is registered.
        *
        * @param proxyName
        *		The name of the IProxy to verify the existence of its registration.
        *
        * @return
        *		A Proxy is currently registered with the given proxyName.
        */
        Model.prototype.hasProxy = function (proxyName) {
            return this.proxyMap[proxyName] != null;
        };

        /**
        * Model multiton factory method.
        *
        * @param key
        *		The multiton key of the instance of Model to create or retrieve.
        *
        * @return
        * 		The singleton instance of the Model.
        */
        Model.getInstance = function (key) {
            if (!Model.instanceMap[key])
                Model.instanceMap[key] = new Model(key);

            return Model.instanceMap[key];
        };

        /**
        * Remove a Model instance
        *
        * @param key
        *		Multiton key identifier for the Model instance to remove.
        */
        Model.removeModel = function (key) {
            delete Model.instanceMap[key];
        };
        Model.MULTITON_MSG = "Model instance for this multiton key already constructed!";

        Model.instanceMap = {};
        return Model;
    })();
    puremvc.Model = Model;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotifier.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IProxy.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/IMediator.ts'/>
///<reference path='../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * A base INotification implementation.
    *
    * PureMVC does not rely upon underlying event models such as the one provided in JavaScript DOM API,
    * and TypeScript does not have an inherent event model.
    *
    * The Observer pattern as implemented within PureMVC exists to support event-driven
    * communication between the application and the actors of the MVC triad (Model, View and
    * Controller).
    *
    * Notifications are not meant to be a replacement for Events in Javascript.
    * Generally, IMediator implementors place event listeners on their view components,
    * which they then handle in the usual way. This may lead to the broadcast of
    * INotifications to trigger ICommands or to communicate with other
    * IMediators. IProxy and ICommand instances communicate
    * with each other and IMediators by broadcasting INotifications.
    *
    * A key difference between JavaScript Events and PureMVC
    * INotifications is that Events follow the 'Chain of Responsibility'
    * pattern, 'bubbling' up the display hierarchy until some parent component handles the
    * Event, while PureMVC INotifications follow a 'Publish/Subscribe'
    * pattern. PureMVC classes need not be related to each other in a parent/child relationship in
    * order to communicate with one another using INotifications.
    */
    var Notification = (function () {
        /**
        * Constructs a Notification instance.
        *
        * @param name
        * 		The name of the notification.
        *
        * @param body
        * 		Body data to send with the Notification.
        *
        * @param type
        * 		Type identifier of the Notification.
        */
        function Notification(name, body, type) {
            if (typeof body === "undefined") { body = null; }
            if (typeof type === "undefined") { type = null; }
            /**
            * The name of the Notification.
            */
            this.name = null;
            /**
            * The body data to send with the Notification.
            */
            this.body = null;
            /**
            * The type identifier of the Notification.
            */
            this.type = null;
            this.name = name;
            this.body = body;
            this.type = type;
        }
        /**
        * Get the name of the Notification instance.
        *
        * @return
        *		The name of the Notification instance.
        */
        Notification.prototype.getName = function () {
            return this.name;
        };

        /**
        * Set the body of the Notification instance.
        *
        * @param body
        * 		The body of the Notification instance.
        */
        Notification.prototype.setBody = function (body) {
            this.body = body;
        };

        /**
        * Get the body of the Notification instance.
        *
        * @return
        *		The body object of the Notification instance.
        */
        Notification.prototype.getBody = function () {
            return this.body;
        };

        /**
        * Set the type of the Notification instance.
        *
        * @param type
        * 		The type of the Notification instance.
        */
        Notification.prototype.setType = function (type) {
            this.type = type;
        };

        /**
        * Get the type of the Notification instance.
        *
        * @return
        *		The type of the Notification instance.
        */
        Notification.prototype.getType = function () {
            return this.type;
        };

        /**
        * Get a textual representation of the Notification instance.
        *
        * @return
        * 		The textual representation of the Notification	instance.
        */
        Notification.prototype.toString = function () {
            var msg = "Notification Name: " + this.getName();
            msg += "\nBody:" + ((this.getBody() == null) ? "null" : this.getBody().toString());
            msg += "\nType:" + ((this.getType() == null) ? "null" : this.getType());
            return msg;
        };
        return Notification;
    })();
    puremvc.Notification = Notification;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IFacade.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IModel.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IView.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IController.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IProxy.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IMediator.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/core/Controller.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/core/Model.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/core/View.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/patterns/observer/Notification.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * A base multiton IFacade implementation.
    *
    * In PureMVC, the Facade class assumes these responsibilities:
    *
    *

    *
Initializing the Model, View and Controller
    * singletons.
    *
Providing all the methods defined by the IModel, IView, &
    * IController interfaces.
    *
Providing the ability to override the specific Model, View and
    * Controller multitons created.
    *
Providing a single point of contact to the application for registering
    * ICommands and notifying IObservers.
    *
    * This Facade implementation is a multiton instance and cannot be instantiated directly,
    * but instead calls the static multiton factory method Facade.getInstance( key ).
    */
    var Facade = (function () {
        /**
        * Constructs a Controller instance.
        *
        * This IFacade implementation is a multiton, so you should not call the
        * constructor directly, but instead call the static multiton factory method
        * Facade.getInstance( key ).
        *
        *
        * @param key
        *		Multiton key for this instance of Facade
        *
        * @throws Error
        *		Throws an error if an instance for this multiton key has already been constructed.
        */
        function Facade(key) {
            /**
            * Local reference to the Model multiton.
            *
            * @protected
            */
            this.model = null;
            /**
            * Local reference to the View multiton.
            *
            * @protected
            */
            this.view = null;
            /**
            * Local reference to the Controller multiton.
            *
            * @protected
            */
            this.controller = null;
            /**
            * The multiton Key for this Core.
            *
            * @protected
            */
            this.multitonKey = null;
            if (Facade.instanceMap[key])
                throw Error(Facade.MULTITON_MSG);

            this.initializeNotifier(key);
            Facade.instanceMap[key] = this;
            this.initializeFacade();
        }
        /**
        * Called automatically by the constructor.
        * Initialize the singleton Facade instance.
        *
        * Override in your subclass to do any subclass specific initializations. Be sure to
        * extend the Facade with the methods and properties on your implementation
        * and call Facade.initializeFacade().
        *
        * @protected
        */
        Facade.prototype.initializeFacade = function () {
            this.initializeModel();
            this.initializeController();
            this.initializeView();
        };

        /**
        * Initialize the Model.
        *
        * Called by the initializeFacade method. Override this method in your
        * subclass of Facade if one or both of the following are true:
        *
        *

        *
 You wish to initialize a different IModel.
        *
 You have Proxys to register with the Model that do not
        * retrieve a reference to the Facade at construction time.
        *
        * If you don't want to initialize a different IModel, call
        * super.initializeModel() at the beginning of your method, then register
        * Proxys.
        *
        * Note: This method is rarely overridden; in practice you are more likely to use a
        * Command to create and register Proxys with the
        * Model, since Proxys with mutable data will likely need to send
        * INotifications and thus will likely want to fetch a reference to the
        * Facade during their construction.
        *
        * @protected
        */
        Facade.prototype.initializeModel = function () {
            if (!this.model)
                this.model = puremvc.Model.getInstance(this.multitonKey);
        };

        /**
        * Initialize the Controller.
        *
        * Called by the initializeFacade method. Override this method in your
        * subclass of Facade if one or both of the following are true:
        *
        *

        *
You wish to initialize a different IController.
        *
You have ICommands to register with the Controller at
        * startup.
        *
        * If you don't want to initialize a different IController, call
        * super.initializeController() at the beginning of your method, then register
        * Commands.
        *
        * @protected
        */
        Facade.prototype.initializeController = function () {
            if (!this.controller)
                this.controller = puremvc.Controller.getInstance(this.multitonKey);
        };

        /**
        * Initialize the View.
        *
        * Called by the initializeFacade method. Override this method in your
        * subclass of Facade if one or both of the following are true:
        *

        *
 You wish to initialize a different IView.
        *
 You have Observers to register with the View
        *
        * If you don't want to initialize a different IView, call
        * super.initializeView() at the beginning of your method, then register
        * IMediator instances.
        *
        * Note: This method is rarely overridden; in practice you are more likely to use a
        * Command to create and register Mediators with the
        * View, since IMediator instances will need to send
        * INotifications and thus will likely want to fetch a reference to the
        * Facade during their construction.
        *
        * @protected
        */
        Facade.prototype.initializeView = function () {
            if (!this.view)
                this.view = puremvc.View.getInstance(this.multitonKey);
        };

        /**
        * Register an ICommand with the IController associating it to a
        * INotification name.
        *
        * @param notificationName
        *		The name of the INotification to associate the ICommand
        *		with.

        * @param commandClassRef
        * 		A reference to the constructor of the ICommand.
        */
        Facade.prototype.registerCommand = function (notificationName, commandClassRef) {
            this.controller.registerCommand(notificationName, commandClassRef);
        };

        /**
        * Remove a previously registered ICommand to INotification
        * mapping from the Controller.
        *
        * @param notificationName
        *		The name of the INotification to remove the ICommand
        *		mapping for.
        */
        Facade.prototype.removeCommand = function (notificationName) {
            this.controller.removeCommand(notificationName);
        };

        /**
        * Check if an ICommand is registered for a given Notification.
        *
        * @param notificationName
        * 		The name of the INotification to verify for the existence of an
        * 		ICommand mapping for.
        *
        * @return
        * 		A Command is currently registered for the given
        *		notificationName.
        */
        Facade.prototype.hasCommand = function (notificationName) {
            return this.controller.hasCommand(notificationName);
        };

        /**
        * Register an IProxy with the Model by name.
        *
        * @param proxy
        *		The IProxy to be registered with the Model.
        */
        Facade.prototype.registerProxy = function (proxy) {
            this.model.registerProxy(proxy);
        };

        /**
        * Retrieve an IProxy from the Model by name.
        *
        * @param proxyName
        * 		The name of the IProxy to be retrieved.
        *
        * @return
        * 		The IProxy previously registered with the given
        *		proxyName.
        */
        Facade.prototype.retrieveProxy = function (proxyName) {
            return this.model.retrieveProxy(proxyName);
        };

        /**
        * Remove an IProxy from the Model by name.
        *
        * @param proxyName
        *		The IProxy to remove from the Model.
        *
        * @return
        *		The IProxy that was removed from the Model
        */
        Facade.prototype.removeProxy = function (proxyName) {
            var proxy;
            if (this.model)
                proxy = this.model.removeProxy(proxyName);

            return proxy;
        };

        /**
        * Check if a Proxy is registered.
        *
        * @param proxyName
        * 		The IProxy to verify the existence of a registration with the
        *		IModel.
        *
        * @return
        * 		A Proxy is currently registered with the given	proxyName.
        */
        Facade.prototype.hasProxy = function (proxyName) {
            return this.model.hasProxy(proxyName);
        };

        /**
        * Register a IMediator with the IView.
        *
        * @param mediator
        *		A reference to the IMediator.
        */
        Facade.prototype.registerMediator = function (mediator) {
            if (this.view)
                this.view.registerMediator(mediator);
        };

        /**
        * Retrieve an IMediator from the IView.
        *
        * @param mediatorName
        * 		The name of the registered Mediator to retrieve.
        *
        * @return
        *		The IMediator previously registered with the given
        *		mediatorName.
        */
        Facade.prototype.retrieveMediator = function (mediatorName) {
            return this.view.retrieveMediator(mediatorName);
        };

        /**
        * Remove an IMediator from the IView.
        *
        * @param mediatorName
        * 		Name of the IMediator to be removed.
        *
        * @return
        *		The IMediator that was removed from the IView
        */
        Facade.prototype.removeMediator = function (mediatorName) {
            var mediator;
            if (this.view)
                mediator = this.view.removeMediator(mediatorName);

            return mediator;
        };

        /**
        * Check if a Mediator is registered or not
        *
        * @param mediatorName
        * 		The name of the IMediator to verify the existence of a registration
        *		for.
        *
        * @return
        * 		An IMediator is registered with the given mediatorName.
        */
        Facade.prototype.hasMediator = function (mediatorName) {
            return this.view.hasMediator(mediatorName);
        };

        /**
        * Notify the IObservers for a particular INotification.
        *
        * This method is left public mostly for backward compatibility, and to allow you to
        * send custom notification classes using the Facade.
        *
        *
        * Usually you should just call sendNotification and pass the parameters,
        * never having to construct the INotification yourself.
        *
        * @param notification
        * 		The INotification to have the IView notify
        *		IObservers	of.
        */
        Facade.prototype.notifyObservers = function (notification) {
            if (this.view)
                this.view.notifyObservers(notification);
        };

        /**
        * Create and send an INotification.
        *
        * Keeps us from having to construct new notification instances in our implementation code.
        *
        * @param name
        *		The name of the notification to send.
        *
        * @param body
        *		The body of the notification to send.
        *
        * @param type
        *		The type of the notification to send.
        */
        Facade.prototype.sendNotification = function (name, body, type) {
            if (typeof body === "undefined") { body = null; }
            if (typeof type === "undefined") { type = null; }
            this.notifyObservers(new puremvc.Notification(name, body, type));
        };

        /**
        * Set the multiton key for this Facade instance.
        *
        * Not called directly, but instead from the constructor when
        * Facade.getInstance(key) is invoked.
        *
        * @param key
        *		The multiton key for this Facade instance to initialize the
        *		Notifier with.
        */
        Facade.prototype.initializeNotifier = function (key) {
            this.multitonKey = key;
        };

        /**
        * Facade multiton factory method.
        *
        * @param key
        *		The multiton key of the instance of Facade to create or retrieve.
        *
        * @return
        * 		The singleton instance of Facade.
        */
        Facade.getInstance = function (key) {
            if (!Facade.instanceMap[key])
                Facade.instanceMap[key] = new Facade(key);

            return Facade.instanceMap[key];
        };

        /**
        * Check if a core is registered or not.
        *
        * @param key
        *		The multiton key for the Core in question.
        *
        * @return
        *		The core is registered with the given key.
        */
        Facade.hasCore = function (key) {
            return Facade.instanceMap[key] ? true : false;
        };

        /**
        * Remove a core.
        *
        * Remove the Model, View, Controller and
        * Facade instances for the given key.
        *
        * @param key
        *		Key identifier of the core to remove.
        */
        Facade.removeCore = function (key) {
            if (!Facade.instanceMap[key])
                return;

            puremvc.Model.removeModel(key);
            puremvc.View.removeView(key);
            puremvc.Controller.removeController(key);

            delete Facade.instanceMap[key];
        };
        Facade.MULTITON_MSG = "Facade instance for this multiton key already constructed!";

        Facade.instanceMap = {};
        return Facade;
    })();
    puremvc.Facade = Facade;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotifier.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IFacade.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/patterns/facade/Facade.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * A base INotifier implementation.
    *
    * MacroCommand, SimpleCommand, Mediator and
    * Proxy all have a need to send Notifications.
    *
    * The INotifier interface provides a common method called
    * sendNotification that relieves implementation code of the necessity to actually
    * construct Notifications.
    *
    * The INotifier interface, which all of the above mentioned classes extend,
    * provides an initialized reference to the Facade singleton, which is required by
    * the convenience method sendNotification	for sending Notifications,
    * but it also eases implementation as these classes have frequent Facade
    * interactions and usually require access to the facade anyway.
    *
    * NOTE: In the MultiCore version of the framework, there is one caveat to notifiers, they
    * cannot send notifications or reach the facade until they have a valid multitonKey.
    *
    * The multitonKey is set:
    *

    *
On a ICommand when it is executed by the Controller.
    *
On a IMediator is registered with the View.
    *
On a IProxy is registered with the Model.
    */
    var Notifier = (function () {
        function Notifier() {
            /**
            * The multiton key for this core.
            *
            * @protected
            */
            this.multitonKey = null;
        }
        /**
        * Initialize a Notifier instance with its cor multiton key.
        *
        * This is how a Notifier gets its multiton key. Calls to
        * sendNotification  or to access the facade will fail until after this method
        * has been called.
        *
        * Mediators, Commands or Proxies may override
        * this method in order to send notifications or access the multiton Facade instance as
        * soon as possible. They CANNOT access the facade in their constructors, since this
        * method will not yet have been called.
        *
        * @param key
        *		The multiton key for this Notifier to use.
        */
        Notifier.prototype.initializeNotifier = function (key) {
            this.multitonKey = key;
        };

        /**
        * Create and send a Notification.
        *
        * Keeps us from having to construct new Notification instances in our
        * implementation code.
        *
        * @param name
        * 		The name of the notification to send.
        *
        * @param body
        * 		The body of the notification.
        *
        * @param type
        * 		The type of the notification.
        */
        Notifier.prototype.sendNotification = function (name, body, type) {
            if (typeof body === "undefined") { body = null; }
            if (typeof type === "undefined") { type = null; }
            if (this.facade())
                this.facade().sendNotification(name, body, type);
        };

        /**
        * Return the multiton Facade instance.
        *
        * @return
        *		The multiton Facade instance.
        *
        * @throws
        *		Throws an error if the multiton key for this Notifier is not yet initialized.
        */
        Notifier.prototype.facade = function () {
            if (this.multitonKey === null)
                throw Error(Notifier.MULTITON_MSG);

            return puremvc.Facade.getInstance(this.multitonKey);
        };

        Notifier.MULTITON_MSG = "multitonKey for this Notifier not yet initialized!";
        return Notifier;
    })();
    puremvc.Notifier = Notifier;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/ICommand.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotifier.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/patterns/observer/Notifier.ts'/>
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * A base ICommand implementation that executes other ICommands.
    *
    * A MacroCommand maintains an list of ICommand constructor references
    * called SubCommands.
    *
    * When execute is called, the MacroCommand instantiates and calls
    * execute on each of its SubCommands turn. Each SubCommand will be
    * passed a reference to the original INotification that was passed to the
    * MacroCommand's execute method.
    *
    * Unlike SimpleCommand, your subclass should not override execute,
    * but instead, should override the initializeMacroCommand method, calling
    * addSubCommand once for each SubCommand to be executed.
    */
    var MacroCommand = (function (_super) {
        __extends(MacroCommand, _super);
        /**
        * Constructs a MacroCommand instance.
        *
        * You should not need to define a constructor in your subclasses, instead, override the
        * initializeMacroCommand method.
        *
        * If your subclass does define a constructor, be  sure to call super().
        */
        function MacroCommand() {
            _super.call(this);
            /**
            * An array of ICommands.
            *
            * @protected
            */
            this.subCommands = null;

            this.subCommands = new Array();
            this.initializeMacroCommand();
        }
        /**
        * Initialize the MacroCommand.
        *
        * In your subclass, override this method to  initialize the MacroCommand's
        * subCommand list with ICommand class references like this:
        *
        *

        *		// Initialize MyMacroCommand
        *		initializeMacroCommand():void
        *		{
        *			this.addSubCommand( FirstCommand );
        *			this.addSubCommand( SecondCommand );
        *			this.addSubCommand( ThirdCommand );
        *		}
        *

        *
        * Note that subCommands may be any ICommand implementor so
        * MacroCommands or SimpleCommands are both acceptable.
        *
        * @protected
        */
        MacroCommand.prototype.initializeMacroCommand = function () {
        };

        /**
        * Add an entry to the subCommands list.
        *
        * The subCommands will be called in First In/First Out (FIFO) order.
        *
        * @param commandClassRef
        *		A reference to the constructor of the ICommand.
        *
        * @protected
        */
        MacroCommand.prototype.addSubCommand = function (commandClassRef) {
            this.subCommands.push(commandClassRef);
        };

        /**
        * Execute this MacroCommand's SubCommands.
        *
        * The SubCommands will be called in First In/First Out (FIFO)
        * order.
        *
        * @param notification
        *		The INotification object to be passed to each SubCommand of
        *		the list.
        *
        * @final
        */
        MacroCommand.prototype.execute = function (notification) {
            var subCommands = this.subCommands.slice(0);
            var len = this.subCommands.length;
            for (var i = 0; i < len; i++) {
                /*
                * Typed any here instead of Function ( won't compile if set to Function
                * because today the compiler consider that Function is not newable and
                * doesn't have a Class type)
                */
                var commandClassRef = subCommands[i];
                var commandInstance = new commandClassRef();
                commandInstance.initializeNotifier(this.multitonKey);
                commandInstance.execute(notification);
            }

            this.subCommands.splice(0);
        };
        return MacroCommand;
    })(puremvc.Notifier);
    puremvc.MacroCommand = MacroCommand;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/ICommand.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotifier.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/patterns/observer/Notifier.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * A base ICommand implementation.
    *
    * Your subclass should override the execute method where your business logic will
    * handle the INotification.
    */
    var SimpleCommand = (function (_super) {
        __extends(SimpleCommand, _super);
        function SimpleCommand() {
            _super.apply(this, arguments);
        }
        /**
        * Fulfill the use-case initiated by the given INotification.
        *
        * In the Command Pattern, an application use-case typically begins with some user action,
        * which results in an INotification being broadcast, which is handled by
        * business logic in the execute method of an ICommand.
        *
        * @param notification
        * 		The INotification to handle.
        */
        SimpleCommand.prototype.execute = function (notification) {
        };
        return SimpleCommand;
    })(puremvc.Notifier);
    puremvc.SimpleCommand = SimpleCommand;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IMediator.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotifier.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotification.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/patterns/observer/Notifier.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * A base IMediator implementation.
    *
    * Typically, a Mediator will be written to serve one specific control or group
    * controls and so, will not have a need to be dynamically named.
    */
    var Mediator = (function (_super) {
        __extends(Mediator, _super);
        /**
        * Constructs a Mediator instance.
        *
        * @param mediatorName
        * 		The name of the Mediator.
        *
        * @param viewComponent
        * 		The view component handled by this Mediator.
        */
        function Mediator(mediatorName, viewComponent) {
            if (typeof mediatorName === "undefined") { mediatorName = null; }
            if (typeof viewComponent === "undefined") { viewComponent = null; }
            _super.call(this);
            /**
            * The name of the Mediator.
            *
            * @protected
            */
            this.mediatorName = null;
            /**
            * The Mediator's view component.
            *
            * @protected
            */
            this.viewComponent = null;

            this.mediatorName = (mediatorName != null) ? mediatorName : Mediator.NAME;
            this.viewComponent = viewComponent;
        }
        /**
        * Get the Mediator instance name.
        *
        * @return
        * 		The Mediator instance name
        */
        Mediator.prototype.getMediatorName = function () {
            return this.mediatorName;
        };

        /**
        * Get the Mediator's view component.
        *
        * Additionally, an implicit getter will usually be defined in the subclass that casts the
        * view object to a type, like this:
        *
        *
        *		getMenu():Menu
        *		{
        *			return <Menu> this.viewComponent;
        *		}
        *
        *
        * @return
        * 		The Mediator's default view component.
        */
        Mediator.prototype.getViewComponent = function () {
            return this.viewComponent;
        };

        /**
        * Set the IMediator's view component.
        *
        * @param viewComponent
        * 		The default view component to set for this Mediator.
        */
        Mediator.prototype.setViewComponent = function (viewComponent) {
            this.viewComponent = viewComponent;
        };

        /**
        * List the INotification names this IMediator is interested in
        * being notified of.
        *
        * @return
        * 		The list of notifications names in which is interested the Mediator.
        */
        Mediator.prototype.listNotificationInterests = function () {
            return new Array();
        };

        /**
        * Handle INotifications.
        *
        *
        * Typically this will be handled in a switch statement, with one 'case' entry per
        * INotification the Mediator is interested in.
        *
        * @param notification
        * 		The notification instance to be handled.
        */
        Mediator.prototype.handleNotification = function (notification) {
        };

        /**
        * Called by the View when the Mediator is registered. This method has to be overridden
        * by the subclass to know when the instance is registered.
        */
        Mediator.prototype.onRegister = function () {
        };

        /**
        * Called by the View when the Mediator is removed. This method has to be overridden
        * by the subclass to know when the instance is removed.
        */
        Mediator.prototype.onRemove = function () {
        };

        Mediator.NAME = 'Mediator';
        return Mediator;
    })(puremvc.Notifier);
    puremvc.Mediator = Mediator;
})(puremvc || (puremvc = {}));
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/IProxy.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/interfaces/INotifier.ts'/>
///<reference path='../../../../../../org/puremvc/typescript/multicore/patterns/observer/Notifier.ts'/>
var puremvc;
(function (puremvc) {
    "use strict";

    /**
    * A base IProxy implementation.
    *
    * In PureMVC, IProxy implementors assume these responsibilities:
    *

    *
Implement a common method which returns the name of the Proxy.
    *
Provide methods for setting and getting the data object.
    *
    * Additionally, IProxy typically:
    *

    *
Maintain references to one or more pieces of model data.
    *
Provide methods for manipulating that data.
    *
Generate INotifications when their model data changes.
    *
Expose their name as a constant called NAME, if they are not
    * instantiated multiple times.
    *
Encapsulate interaction with local or remote services used to fetch and persist model
    * data.
    */
    var Proxy = (function (_super) {
        __extends(Proxy, _super);
        /**
        * Constructs a Proxy instance.
        *
        * @param proxyName
        * 		The name of the Proxy instance.
        *
        * @param data
        * 		An initial data object to be held by the Proxy.
        */
        function Proxy(proxyName, data) {
            if (typeof proxyName === "undefined") { proxyName = null; }
            if (typeof data === "undefined") { data = null; }
            _super.call(this);
            /**
            * The name of the Proxy.
            *
            * @protected
            */
            this.proxyName = null;
            /**
            * The data object controlled by the Proxy.
            *
            * @protected
            */
            this.data = null;

            this.proxyName = (proxyName != null) ? proxyName : Proxy.NAME;

            if (data != null)
                this.setData(data);
        }
        /**
        * Get the name of the Proxy> instance.
        *
        * @return
        * 		The name of the Proxy> instance.
        */
        Proxy.prototype.getProxyName = function () {
            return this.proxyName;
        };

        /**
        * Set the data of the Proxy> instance.
        *
        * @param data
        * 		The data to set for the Proxy> instance.
        */
        Proxy.prototype.setData = function (data) {
            this.data = data;
        };

        /**
        * Get the data of the Proxy> instance.
        *
        * @return
        * 		The data held in the Proxy instance.
        */
        Proxy.prototype.getData = function () {
            return this.data;
        };

        /**
        * Called by the Model when the Proxy is registered. This method has to be
        * overridden by the subclass to know when the instance is registered.
        */
        Proxy.prototype.onRegister = function () {
        };

        /**
        * Called by the Model when the Proxy is removed. This method has to be
        * overridden by the subclass to know when the instance is removed.
        */
        Proxy.prototype.onRemove = function () {
        };

        Proxy.NAME = "Proxy";
        return Proxy;
    })(puremvc.Notifier);
    puremvc.Proxy = Proxy;
})(puremvc || (puremvc = {}));


text:
/*
 *	 INTERFACE ROUTINES
 *		ExecNestLoop	 - process a nestloop join of two plans
 *		ExecInitNestLoop - initialize the join
 *		ExecEndNestLoop  - shut down the join
 */

#include "postgres.h"

#include "cdb/cdbvars.h"
#include "executor/execdebug.h"
#include "executor/nodeNestloop.h"
#include "optimizer/clauses.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"

extern bool Test_print_prefetch_joinqual;

static void splitJoinQualExpr(NestLoopState *nlstate);
static void extractFuncExprArgs(FuncExprState *fstate, List **lclauses, List **rclauses);

/* ----------------------------------------------------------------
 *		ExecNestLoop(node)
 *
 * old comments
 *		Returns the tuple joined from inner and outer tuples which
 *		satisfies the qualification clause.
 *
 *		It scans the inner relation to join with current outer tuple.
 *
 *		If none is found, next tuple from the outer relation is retrieved
 *		and the inner relation is scanned from the beginning again to join
 *		with the outer tuple.
 *
 *		NULL is returned if all the remaining outer tuples are tried and
 *		all fail to join with the inner tuples.
 *
 *		NULL is also returned if there is no tuple from inner relation.
 *
 *		Conditions:
 *		  -- outerTuple contains current tuple from outer relation and
 *			 the right son(inner relation) maintains "cursor" at the tuple
 *			 returned previously.
 *				This is achieved by maintaining a scan position on the outer
 *				relation.
 *
 *		Initial States:
 *		  -- the outer child and the inner child
 *			   are prepared to return the first tuple.
 * ----------------------------------------------------------------
 */
static TupleTableSlot *
ExecNestLoop_guts(NestLoopState *node)
{
	NestLoop   *nl;
	PlanState  *innerPlan;
	PlanState  *outerPlan;
	TupleTableSlot *outerTupleSlot;
	TupleTableSlot *innerTupleSlot;
	List	   *joinqual;
	List	   *otherqual;
	ExprContext *econtext;
	ListCell   *lc;

	/*
	 * get information from the node
	 */
	ENL1_printf("getting info from node");

	nl = (NestLoop *) node->js.ps.plan;
	joinqual = node->js.joinqual;
	otherqual = node->js.ps.qual;
	outerPlan = outerPlanState(node);
	innerPlan = innerPlanState(node);
	econtext = node->js.ps.ps_ExprContext;

	/*
	 * Reset per-tuple memory context to free any expression evaluation
	 * storage allocated in the previous tuple cycle.  Note this can't happen
	 * until we're done projecting out tuples from a join tuple.
	 */
	ResetExprContext(econtext);

	/*
	 * MPP-4165: My fix for MPP-3300 was correct in that we avoided
	 * the *deadlock* but had very unexpected (and painful)
	 * performance characteristics: we basically de-pipeline and
	 * de-parallelize execution of any query which has motion below
	 * us.
	 *
	 * So now prefetch_inner is set (see createplan.c) if we have *any* motion
	 * below us. If we don't have any motion, it doesn't matter.
	 *
	 * See motion_sanity_walker() for details on how a deadlock may occur.
	 */
	if (node->prefetch_inner)
	{
		/*
		 * Prefetch inner is Greenplum specific behavior.
		 * However, inner plan may depend on outer plan as
		 * outerParams. If so, we have to fake those params
		 * to avoid null pointer reference issue. And because
		 * of the nestParams, those inner results prefetched
		 * will be discarded (following code will rescan inner,
		 * even if inner's top is material node because of chgParam
		 * it will be re-executed too) that it is safe to fake
		 * nestParams here. The target is to materialize motion scan.
		 */
		if (nl->nestParams)
		{
			EState	   *estate = node->js.ps.state;

			econtext->ecxt_outertuple = ExecInitNullTupleSlot(estate,
															  ExecGetResultType(outerPlan));
			fake_outer_params(&(node->js));
		}

		innerTupleSlot = ExecProcNode(innerPlan);
		node->reset_inner = true;
		econtext->ecxt_innertuple = innerTupleSlot;

		if (TupIsNull(innerTupleSlot))
		{
			/*
			 * Finished one complete scan of the inner side. Mark it here
			 * so that we don't keep checking for inner nulls at subsequent
			 * iterations.
			 */
			node->nl_innerSideScanned = true;
		}

		if ((node->js.jointype == JOIN_LASJ_NOTIN) &&
				(!node->nl_innerSideScanned) &&
				(node->nl_InnerJoinKeys && isJoinExprNull(node->nl_InnerJoinKeys, econtext)))
		{
			/*
			 * If LASJ_NOTIN and a null was found on the inner side, all tuples
			 * We'll read no more from either inner or outer subtree. To keep our
			 * in outer sider will be treated as "not in" tuples in inner side.
			 */
			ENL1_printf("Found NULL tuple on the inner side, clean out");
			return NULL;
		}

		ExecReScan(innerPlan);
		ResetExprContext(econtext);

		node->prefetch_inner = false;
		node->reset_inner = false;
	}

	/*
	 * Prefetch JoinQual to prevent motion hazard.
	 *
	 * See ExecPrefetchJoinQual() for details.
	 */
	if (node->prefetch_joinqual)
	{
		ExecPrefetchJoinQual(&node->js);
		node->prefetch_joinqual = false;
	}

	/*
	 * Ok, everything is setup for the join so now loop until we return a
	 * qualifying join tuple.
	 */
	ENL1_printf("entering main loop");

	for (;;)
	{
		/*
		 * If we don't have an outer tuple, get the next one and reset the
		 * inner scan.
		 */
		if (node->nl_NeedNewOuter)
		{
			ENL1_printf("getting new outer tuple");
			outerTupleSlot = ExecProcNode(outerPlan);

			/*
			 * if there are no more outer tuples, then the join is complete..
			 */
			if (TupIsNull(outerTupleSlot))
			{
				ENL1_printf("no outer tuple, ending join");
				return NULL;
			}

			ENL1_printf("saving new outer tuple information");
			econtext->ecxt_outertuple = outerTupleSlot;
			node->nl_NeedNewOuter = false;
			node->nl_MatchedOuter = false;

			/*
			 * fetch the values of any outer Vars that must be passed to the
			 * inner scan, and store them in the appropriate PARAM_EXEC slots.
			 */
			foreach(lc, nl->nestParams)
			{
				NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
				int			paramno = nlp->paramno;
				ParamExecData *prm;

				prm = &(econtext->ecxt_param_exec_vals[paramno]);
				/* Param value should be an OUTER_VAR var */
				Assert(IsA(nlp->paramval, Var));
				Assert(nlp->paramval->varno == OUTER_VAR);
				Assert(nlp->paramval->varattno > 0);
				prm->value = slot_getattr(outerTupleSlot,
										  nlp->paramval->varattno,
										  &(prm->isnull));
				/* Flag parameter value as changed */
				innerPlan->chgParam = bms_add_member(innerPlan->chgParam,
													 paramno);
			}

			/*
			 * now rescan the inner plan
			 */
			ENL1_printf("rescanning inner plan");
			if (node->require_inner_reset || node->reset_inner)
			{
				ExecReScan(innerPlan);
				node->reset_inner = false;
			}
		}

		/*
		 * we have an outerTuple, try to get the next inner tuple.
		 */
		ENL1_printf("getting new inner tuple");

		innerTupleSlot = ExecProcNode(innerPlan);

		node->reset_inner = true;
		econtext->ecxt_innertuple = innerTupleSlot;

		if (TupIsNull(innerTupleSlot))
		{
			ENL1_printf("no inner tuple, need new outer tuple");

			node->nl_NeedNewOuter = true;
			/*
			 * Finished one complete scan of the inner side. Mark it here
			 * so that we don't keep checking for inner nulls at subsequent
			 * iterations.
			 */
			node->nl_innerSideScanned = true;

			if (!node->nl_MatchedOuter &&
				(node->js.jointype == JOIN_LEFT ||
				 node->js.jointype == JOIN_ANTI ||
				 node->js.jointype == JOIN_LASJ_NOTIN))
			{
				/*
				 * We are doing an outer join and there were no join matches
				 * for this outer tuple.  Generate a fake join tuple with
				 * nulls for the inner tuple, and return it if it passes the
				 * non-join quals.
				 */
				econtext->ecxt_innertuple = node->nl_NullInnerTupleSlot;

				ENL1_printf("testing qualification for outer-join tuple");

				if (otherqual == NIL || ExecQual(otherqual, econtext, false))
				{
					/*
					 * qualification was satisfied so we project and return
					 * the slot containing the result tuple using
					 * ExecProject().
					 */
					ENL1_printf("qualification succeeded, projecting tuple");

					return ExecProject(node->js.ps.ps_ProjInfo, NULL);
				}
				else
					InstrCountFiltered2(node, 1);
			}

			/*
			 * Otherwise just return to top of loop for a new outer tuple.
			 */
			continue;
		}

		if ((node->js.jointype == JOIN_LASJ_NOTIN) &&
				(!node->nl_innerSideScanned) &&
				(node->nl_InnerJoinKeys && isJoinExprNull(node->nl_InnerJoinKeys, econtext)))
		{
			/*
			 * If LASJ_NOTIN and a null was found on the inner side, all tuples
			 * We'll read no more from either inner or outer subtree. To keep our
			 * in outer sider will be treated as "not in" tuples in inner side.
			 */
			ENL1_printf("Found NULL tuple on the inner side, clean out");
			return NULL;
		}

		/*
		 * at this point we have a new pair of inner and outer tuples so we
		 * test the inner and outer tuples to see if they satisfy the node's
		 * qualification.
		 *
		 * Only the joinquals determine MatchedOuter status, but all quals
		 * must pass to actually return the tuple.
		 */
		ENL1_printf("testing qualification");

		if (ExecQual(joinqual, econtext, node->nl_qualResultForNull))
		{
			node->nl_MatchedOuter = true;

			/* In an antijoin, we never return a matched tuple */
			if (node->js.jointype == JOIN_LASJ_NOTIN || node->js.jointype == JOIN_ANTI)
			{
				node->nl_NeedNewOuter = true;
				continue;		/* return to top of loop */
			}

			/*
			 * In a semijoin, we'll consider returning the first match, but
			 * after that we're done with this outer tuple.
			 */
			if (node->js.jointype == JOIN_SEMI)
				node->nl_NeedNewOuter = true;

			if (otherqual == NIL || ExecQual(otherqual, econtext, false))
			{
				/*
				 * qualification was satisfied so we project and return the
				 * slot containing the result tuple using ExecProject().
				 */
				TupleTableSlot *result;

				ENL1_printf("qualification succeeded, projecting tuple");

				result = ExecProject(node->js.ps.ps_ProjInfo, NULL);

				return result;
			}
			else
				InstrCountFiltered2(node, 1);
		}
		else
			InstrCountFiltered1(node, 1);

		/*
		 * Tuple fails qual, so free per-tuple memory and try again.
		 */
		ResetExprContext(econtext);

		ENL1_printf("qualification failed, looping");
	}
}

TupleTableSlot *
ExecNestLoop(NestLoopState *node)
{
	TupleTableSlot *result;

	result = ExecNestLoop_guts(node);

	if (TupIsNull(result))
	{
		/*
		 * CDB: We'll read no more from inner subtree. To keep our
		 * sibling QEs from being starved, tell source QEs not to
		 * clog up the pipeline with our never-to-be-consumed
		 * data.
		 */
		ExecSquelchNode((PlanState *) node);
	}

	return result;
}

/* ----------------------------------------------------------------
 *		ExecInitNestLoop
 * ----------------------------------------------------------------
 */
NestLoopState *
ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
{
	NestLoopState *nlstate;

	/* check for unsupported flags */
	Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));

	NL1_printf("ExecInitNestLoop: %s\n",
			   "initializing node");

	/*
	 * create state structure
	 */
	nlstate = makeNode(NestLoopState);
	nlstate->js.ps.plan = (Plan *) node;
	nlstate->js.ps.state = estate;

	nlstate->shared_outer = node->shared_outer;

	nlstate->prefetch_inner = node->join.prefetch_inner;
	nlstate->prefetch_joinqual = node->join.prefetch_joinqual;

	if (Test_print_prefetch_joinqual && nlstate->prefetch_joinqual)
		elog(NOTICE,
			 "prefetch join qual in slice %d of plannode %d",
			 currentSliceId, ((Plan *) node)->plan_node_id);

	/*CDB-OLAP*/
	nlstate->reset_inner = false;
	nlstate->require_inner_reset = !node->singleton_outer;

	/*
	 * Miscellaneous initialization
	 *
	 * create expression context for node
	 */
	ExecAssignExprContext(estate, &nlstate->js.ps);

	/*
	 * initialize child expressions
	 */
	nlstate->js.ps.targetlist = (List *)
		ExecInitExpr((Expr *) node->join.plan.targetlist,
					 (PlanState *) nlstate);
	nlstate->js.ps.qual = (List *)
		ExecInitExpr((Expr *) node->join.plan.qual,
					 (PlanState *) nlstate);
	nlstate->js.jointype = node->join.jointype;
	nlstate->js.joinqual = (List *)
		ExecInitExpr((Expr *) node->join.joinqual,
					 (PlanState *) nlstate);

	/*
	 * initialize child nodes
	 *
	 * If we have no parameters to pass into the inner rel from the outer,
	 * tell the inner child that cheap rescans would be good.  If we do have
	 * such parameters, then there is no point in REWIND support at all in the
	 * inner child, because it will always be rescanned with fresh parameter
	 * values.
	 */

	/*
	 * XXX ftian: Because share input need to make the whole thing into a tree,
	 * we can put the underlying share only under one shareinputscan.  During execution,
	 * we need the shareinput node that has underlying subtree be inited/executed first.
	 * This means,
	 * 	1. Init and first ExecProcNode call must be in the same order
	 *	2. Init order above is the same as the tree walking order in cdbmutate.c
	 * For nest loop join, it is more strange than others.  Depends on prefetch_inner,
	 * the execution order may change.  Handle this correctly here.
	 *
	 * Until we find a better way to handle the dependency of ShareInputScan on
	 * execution order, this is pretty much what we have to deal with.
	 */
	if (node->nestParams == NIL)
		eflags |= EXEC_FLAG_REWIND;
	else
		eflags &= ~EXEC_FLAG_REWIND;
	if (nlstate->prefetch_inner)
	{
		innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate, eflags);
		if (!node->shared_outer)
			outerPlanState(nlstate) = ExecInitNode(outerPlan(node), estate, eflags);
	}
	else
	{
		if (!node->shared_outer)
			outerPlanState(nlstate) = ExecInitNode(outerPlan(node), estate, eflags);
		innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate, eflags);
	}

	/*
	 * tuple table initialization
	 */
	ExecInitResultTupleSlot(estate, &nlstate->js.ps);

	switch (node->join.jointype)
	{
		case JOIN_INNER:
		case JOIN_SEMI:
			break;
		case JOIN_LEFT:
		case JOIN_ANTI:
		case JOIN_LASJ_NOTIN:
			nlstate->nl_NullInnerTupleSlot =
				ExecInitNullTupleSlot(estate,
								 ExecGetResultType(innerPlanState(nlstate)));
			break;
		default:
			elog(ERROR, "unrecognized join type: %d",
				 (int) node->join.jointype);
	}

	/*
	 * initialize tuple type and projection info
	 */
	ExecAssignResultTypeFromTL(&nlstate->js.ps);
	ExecAssignProjectionInfo(&nlstate->js.ps, NULL);

	/*
	 * finally, wipe the current outer tuple clean.
	 */
	nlstate->nl_NeedNewOuter = true;
	nlstate->nl_MatchedOuter = false;

    if (node->join.jointype == JOIN_LASJ_NOTIN)
    {
    	splitJoinQualExpr(nlstate);
    	/*
    	 * For LASJ_NOTIN, when we evaluate the join condition, we want to
    	 * return true when one of the conditions is NULL, so we exclude
    	 * that tuple from the output.
    	 */
		nlstate->nl_qualResultForNull = true;
    }
    else
    {
        nlstate->nl_qualResultForNull = false;
    }

	NL1_printf("ExecInitNestLoop: %s\n",
			   "node initialized");

	return nlstate;
}

/* ----------------------------------------------------------------
 *		ExecEndNestLoop
 *
 *		closes down scans and frees allocated storage
 * ----------------------------------------------------------------
 */
void
ExecEndNestLoop(NestLoopState *node)
{
	NL1_printf("ExecEndNestLoop: %s\n",
			   "ending node processing");

	/*
	 * Free the exprcontext
	 */
	ExecFreeExprContext(&node->js.ps);

	/*
	 * clean out the tuple table
	 */
	ExecClearTuple(node->js.ps.ps_ResultTupleSlot);

	/*
	 * close down subplans
	 */
	if (!node->shared_outer)
		ExecEndNode(outerPlanState(node));
	ExecEndNode(innerPlanState(node));

	NL1_printf("ExecEndNestLoop: %s\n",
			   "node processing ended");
}

/* ----------------------------------------------------------------
 *		ExecReScanNestLoop
 * ----------------------------------------------------------------
 */
void
ExecReScanNestLoop(NestLoopState *node)
{
	PlanState  *outerPlan = outerPlanState(node);

	/*
	 * If outerPlan->chgParam is not null then plan will be automatically
	 * re-scanned by first ExecProcNode.
	 */
	if (outerPlan->chgParam == NULL)
		ExecReScan(outerPlan);

	/*
	 * innerPlan is re-scanned for each new outer tuple and MUST NOT be
	 * re-scanned from here or you'll get troubles from inner index scans when
	 * outer Vars are used as run-time keys...
	 */

	node->nl_NeedNewOuter = true;
	node->nl_MatchedOuter = false;
	node->nl_innerSideScanned = false;
}

/* ----------------------------------------------------------------
 * splitJoinQualExpr
 *
 * Deconstruct the join clauses into outer and inner argument values, so
 * that we can evaluate those subexpressions separately. Note: for constant
 * expression we don't need to split (MPP-21294). However, if constant expressions
 * have peer splittable expressions we *do* split those.
 *
 * This is used for NOTIN joins, as we need to look for NULLs on both
 * inner and outer side.
 * ----------------------------------------------------------------
 */
static void
splitJoinQualExpr(NestLoopState *nlstate)
{
	List *lclauses = NIL;
	List *rclauses = NIL;
	ListCell *lc = NULL;

	foreach(lc, nlstate->js.joinqual)
	{
		GenericExprState *exprstate = (GenericExprState *) lfirst(lc);
		switch (exprstate->xprstate.type)
		{
		case T_FuncExprState:
			extractFuncExprArgs((FuncExprState *) exprstate, &lclauses, &rclauses);
			break;
		case T_BoolExprState:
		{
			BoolExprState *bstate = (BoolExprState *) exprstate;
			ListCell *argslc = NULL;
			foreach(argslc,bstate->args)
			{
				FuncExprState *fstate = (FuncExprState *) lfirst(argslc);
				Assert(IsA(fstate, FuncExprState));
				extractFuncExprArgs(fstate, &lclauses, &rclauses);
			}
			break;
		}
		case T_ExprState:
			/* For constant expression we don't need to split */
			if (exprstate->xprstate.expr->type == T_Const)
			{
				/*
				 * Constant expressions do not need to be splitted into left and
				 * right as they don't need to be considered for NULL value special
				 * cases
				 */
				continue;
			}

			elog(ERROR, "unexpected expression type in NestLoopJoin qual");

			break; /* Unreachable */
		default:
			elog(ERROR, "unexpected expression type in NestLoopJoin qual");
		}
	}
	Assert(NIL == nlstate->nl_InnerJoinKeys && NIL == nlstate->nl_OuterJoinKeys);
	nlstate->nl_InnerJoinKeys = rclauses;
	nlstate->nl_OuterJoinKeys = lclauses;
}

/* ----------------------------------------------------------------
 * extractFuncExprArgs
 *
 * Extract the arguments of a FuncExpr and append them into two
 * given lists:
 *   - lclauses for the left side of the expression,
 *   - rclauses for the right side
 *
 * This function is only used for LASJ. Once we find a NULL from inner side, we
 * can skip the join and just return an empty set as result. This is only true
 * if the equality operator is strict, that is, if a tuple from inner side is
 * NULL then the equality operator returns NULL.
 *
 * If the number of arguments is not two, we just return leaving lclauses and
 * rclauses remaining NULL. In this case, the LASJ join would be actually
 * performed.
 * ----------------------------------------------------------------
 */
static void
extractFuncExprArgs(FuncExprState *fstate, List **lclauses, List **rclauses)
{
	Node *clause;

	if (list_length(fstate->args) != 2)
		return;

	/* Check for strictness of the equality operator */
	clause = (Node *)fstate->xprstate.expr;
	if ((is_opclause(clause) && op_strict(((OpExpr *) clause)->opno)) ||
			(is_funcclause(clause) && func_strict(((FuncExpr *) clause)->funcid)))
	{
		*lclauses = lappend(*lclauses, linitial(fstate->args));
		*rclauses = lappend(*rclauses, lsecond(fstate->args));
	}
}

redpajama_set_name: RedPajamaGithub


text:
This repository contains the following simple command line tools written in
perl:

- cdhist    : Keep history of 'cd' directories for quicker access
- cstyle    : Style checker for C code
- regex     : Test out regular expressions
- rext      : Change the file extensions on files

## cdhist

This program keeps track of all the recently used directories so that you can
easily cd into them. If you use zsh (you should definitely be using zsh), then
just source the `cdh.zsh` file in your `.zshrc`.

If you are using bash, switch to zsh. Otherwise, just add the following
functions need to your `.bashrc`:

```sh
alias cdp='cdhist print'
alias cds='cdh_goto'
alias cd='cdh_add'

cdh_goto()
{
    if [ $# == 0 ]; then
        ARG=0;
    else
        ARG=${1};
    fi
    cd "`cdhist goto "$ARG"`"
}

cdh_add()
{
    if [ $# != 0 ]; then
        cdhist add $*
    fi
    \cd $*
}
```

Then, `cdp` will print out the last 10 working directories and their labels,
`cds [num]` will go to directory `num` (defaults to `num = 0`), and `cd` will
work as normal while additionally adding directories to your history.

## cstyle

This script quickly checks some simple style rules for C code. It will catch
things like end-of-line whitespace, tab indentations, and spaces around
operators. The style used by this script is my personal style; you might not
like some of the things in it.

## regex

Test regular expressions. Pass it a regular expression as an argument, then
type into `stdin` to check for matches.

## rext

Change file extensions. Wrote this a long time ago because I didn't want to
learn anything new. Should work, but I forget the syntax

## Copyright

Copyright (c) 2013-14 Brian Kubisiak <velentr.rc@gmail.com>

See LICENSE for details.


text:
require 'spec_helper'

describe Workable::Client do
  let(:client) { described_class.new(api_key: 'test', subdomain: 'subdomain') }
  let(:headers){ { 'Authorization' => 'Bearer test', 'User-Agent' => 'Workable Ruby Client' } }

  describe '#new' do
    it 'raises an error on missing api_key / subdomain' do
      expect { described_class.new }.to raise_error(Workable::Errors::InvalidConfiguration)
      expect { described_class.new(api_key: 'key') }.to raise_error(Workable::Errors::InvalidConfiguration)
      expect { described_class.new(subdomain: 'subdomain') }.to raise_error(Workable::Errors::InvalidConfiguration)
    end

    it 'creates new instance when all required arguments are provided' do
      expect(described_class.new(api_key: 'key', subdomain: 'subdomain')).to be_kind_of(described_class)
    end
  end

  describe '#about' do
    it 'returns information about company as a hash' do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/')
        .to_return(status: 200, body: about_json_fixture)
      expect(client.about['name']).to eq('Groove Tech')
    end
  end

  describe '#members' do
    it 'returns array of members' do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/members')
        .to_return(status: 200, body: members_json_fixture)

      expect(client.members).to be_kind_of(Array)
      expect(client.members[0]).to eq(
        'id' => '13e0eb0e',
        'name' => 'Eduardo Vallente',
        'headline' => 'Operations Manager',
        'email' => 'eduardo.vallente@workabledemo.com',
        'role' => 'admin'
      )
    end
  end

  describe '#recruiters' do
    it 'returns array of recruiters' do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/recruiters')
        .to_return(status: 200, body: recruiters_json_fixture)

      expect(client.recruiters).to be_kind_of(Array)
      expect(client.recruiters[0]).to eq(
        'id' => '19782abc',
        'name' => 'Nadia Sawahla',
        'email' => 'nadia.sawahla@name.com'
      )
    end
  end

  describe '#stages' do
    it 'returns array of stages' do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/stages')
        .to_return(status: 200, body: stages_json_fixture)

      expect(client.stages).to be_kind_of(Array)
      expect(client.stages[0]).to eq(
        'slug' => 'sourced',
        'name' => 'Sourced',
        'kind' => 'sourced',
        'position' => 0
      )
    end
  end

  describe '#jobs' do
    context 'happy path' do
      before do
        stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs')
          .with(headers: headers)
          .to_return(status: 200, body: jobs_index_json_fixture)
      end

      it 'returns collection of posted jobs' do
        expect(client.jobs).to be_kind_of(Workable::Collection)
        expect(client.jobs.data).to be_kind_of(Array)
        expect(client.jobs.data[0]).to include('title' => 'Sales Intern', 'full_title' => 'Sales Intern - US/3/SI')
        expect(client.jobs.data.size).to eq(3)
      end

      it 'includes next page method that returns next collection' do
        stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs?limit=3&since_id=2700d6df')
          .with(headers: headers)
          .to_return(status: 200, body: jobs_index_json_fixture)

        jobs = client.jobs.fetch_next_page
        expect(jobs).to be_kind_of(Workable::Collection)
        expect(client.jobs.data).to be_kind_of(Array)
      end
    end

    context 'sad path' do
      it 'raises exception on not authorized error (401)' do
        stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs')
          .to_return(status: 401, body: '{"error":"Not authorized"}')

        expect { client.jobs }.to raise_error(Workable::Errors::NotAuthorized)
      end

      it 'raises exception when status code differs from 200' do
        stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs')
          .to_return(status: 500, body: '')

        expect { client.jobs }.to raise_error(Workable::Errors::InvalidResponse)
      end
    end
  end

  describe '#job_details' do
    it 'returns details of given job' do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/03FF356C8B')
        .to_return(status: 200, body: job_json_fixture)

      expect(client.job_details('03FF356C8B')).to be_kind_of(Hash)
    end

    it 'raises an exception when job is not found' do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/invalid')
        .to_return(status: 404, body: '{"error":"Not found"}')

      expect { client.job_details('invalid') }.to raise_error(Workable::Errors::NotFound)
    end
  end

  describe '#job_questions' do
    it 'returns questions for given job' do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/03FF356C8B/questions')
        .to_return(status: 200, body: job_questions_json_fixture)

      questions = client.job_questions('03FF356C8B')
      expect(questions).to be_kind_of(Array)
      expect(questions[0]['body']).to eq('Explain one aspect of this role you believe you will excel at.')
    end
  end

  describe '#job_application_form' do
    it 'returns application form for given job' do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/03FF356C8B/application_form')
        .to_return(status: 200, body: job_application_form_fixture)

      form = client.job_application_form('03FF356C8B')
      expect(form).to be_kind_of(Hash)
      expect(form.has_key?('questions')).to eq true
      expect(form['form_fields'][0]).to eq({
        'key' => 'phone',
        'label' => 'Phone',
        'type' => 'string',
        'required' => true
      })

    end
  end

  describe '#job_members' do
    it "returns array of job's members" do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/job_slug/members')
        .to_return(status: 200, body: members_json_fixture)

      expect(client.job_members('job_slug')).to be_kind_of(Array)
      expect(client.job_members('job_slug')[0]).to eq(
        'id' => '13e0eb0e',
        'name' => 'Eduardo Vallente',
        'headline' => 'Operations Manager',
        'email' => 'eduardo.vallente@workabledemo.com',
        'role' => 'admin'
      )
    end
  end

  describe 'job_recruiters' do
    it "returns array of job's recruiters" do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/job_slug/recruiters')
        .to_return(status: 200, body: recruiters_json_fixture)

      expect(client.job_recruiters('job_slug')).to be_kind_of(Array)
      expect(client.job_recruiters('job_slug')[0]).to eq(
        'id' => '19782abc',
        'name' => 'Nadia Sawahla',
        'email' => 'nadia.sawahla@name.com'
      )
    end
  end

  describe '#job_candidates' do
    context 'happy path' do
      let(:candidates){ client.job_candidates('03FF356C8B') }
      before do
        stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/03FF356C8B/candidates')
          .to_return(status: 200, body: job_candidates_json_fixture)
      end

      it 'returns collection of candidates for given job' do
        expect(candidates).to be_kind_of(Workable::Collection)
        expect(candidates.data[0]['name']).to eq('Lakita Marrero')
      end

      it 'includes next page method that returns next collection' do
        stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/subdomain/candidates?limit=3&since_id=2700d6df')
          .with(headers: headers)
          .to_return(status: 200, body: job_candidates_json_fixture)

        next_candidates = candidates.fetch_next_page
        expect(next_candidates).to be_kind_of(Workable::Collection)
        expect(next_candidates.data).to be_kind_of(Array)
      end
    end

    context 'sad path' do
      it 'raises exception on to long requests' do
        stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/03FF356C8B/candidates')
          .to_return(status: 503, body: '{"error":"Not authorized"}')

        expect { client.job_candidates('03FF356C8B') }.to raise_error(Workable::Errors::RequestToLong)
      end
    end
  end

  describe '#job_candidate' do
    it 'returns detailed info about given candidate' do
      stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/job-slug/candidates/some-id')
        .to_return(status: 200, body: job_candidate_json_fixture)

      expect(client.job_candidate('job-slug', 'some-id')['name']).to eq('Cindy Sawyers')
    end
  end

  describe '#create_job_candidate' do
    it 'POSTs requests and parses response' do
      stub_request(:post, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/slug/candidates')
        .with(body: new_candidate_hash_fixture.to_json)
        .to_return(status: 200, body: new_candidate_response_json_fixture)

      candidate = client.create_job_candidate(new_candidate_hash_fixture, 'slug')
      expect(candidate['id']).to eq('3fc9a80f')
    end
  end

  describe '#create_comment' do
    let(:candidate_id) { '123456' }
    let(:member_id) { '314' }
    let(:comment_text) { "Hire this person!" }
    let(:body) do
      {
        member_id: member_id,
        comment: {
          body: comment_text,
          policy: [],
          attachment: nil
        }
      }
    end

    it 'submits POST request' do
      stub = stub_request(:post, 'https://www.workable.com/spi/v3/accounts/subdomain/candidates/123456/comments')
        .with(body: body.to_json)

      client.create_comment(candidate_id, member_id, comment_text)
      expect(stub).to have_been_requested.once
    end
  end

  describe '#disqualify' do
    let(:candidate_id) { '123456' }
    let(:member_id) { '314' }
    let(:reason) { 'Lacks experience.' }
    let(:body) do
      {
        member_id: member_id,
        disqualification_reason: reason
      }
    end

    it 'submits POST request' do
      stub = stub_request(:post, 'https://www.workable.com/spi/v3/accounts/subdomain/candidates/123456/disqualify')
        .with(body: body.to_json)

      client.disqualify(candidate_id, member_id, reason)
      expect(stub).to have_been_requested.once
    end
  end

  describe '#revert' do
    let(:candidate_id) { '123456' }
    let(:member_id) { '314' }
    let(:body) do
      { member_id: member_id }
    end

    it 'submits POST request' do
      stub = stub_request(:post, 'https://www.workable.com/spi/v3/accounts/subdomain/candidates/123456/revert')
        .with(body: body.to_json)

      client.revert(candidate_id, member_id)
      expect(stub).to have_been_requested.once
    end
  end

  describe '#copy' do
    let(:candidate_id) { '123456' }
    let(:member_id) { '314' }
    let(:shortcode) { 'GROOV005' }
    let(:stage) { 'applied' }
    let(:body) do
      {
        member_id: member_id,
        target_job_shortcode: shortcode,
        target_stage: stage
      }
    end

    it 'POSTs requests and parses response' do
      stub_request(:post, 'https://www.workable.com/spi/v3/accounts/subdomain/candidates/123456/copy')
        .with(body: body.to_json)
        .to_return(status: 201, body: copy_candidate_response_json_fixture)

      candidate = client.copy(candidate_id, member_id, shortcode, stage)
      expect(candidate['id']).to eq(candidate_id)
    end
  end

  describe '#relocate' do
    let(:candidate_id) { '123456' }
    let(:member_id) { '314' }
    let(:shortcode) { 'GROOV005' }
    let(:stage) { 'applied' }
    let(:body) do
      {
        member_id: member_id,
        target_job_shortcode: shortcode,
        target_stage: stage
      }
    end

    it 'POSTs requests and parses response' do
      stub_request(:post, 'https://www.workable.com/spi/v3/accounts/subdomain/candidates/123456/relocate')
        .with(body: body.to_json)
        .to_return(status: 201, body: relocate_candidate_response_json_fixture)

      candidate = client.relocate(candidate_id, member_id, shortcode, stage)
      expect(candidate['id']).to eq(candidate_id)
    end
  end

  describe '#move' do
    let(:candidate_id) { '123456' }
    let(:member_id) { '314' }
    let(:stage ) { 'applied' }
    let(:body) do
      {
        member_id: member_id,
        target_stage: stage
      }
    end

    it 'submits POST request' do
      stub = stub_request(:post, 'https://www.workable.com/spi/v3/accounts/subdomain/candidates/123456/move')
        .with(body: body.to_json)

      client.move(candidate_id, member_id, stage)
      expect(stub).to have_been_requested.once
    end
  end

  describe '#create_rating' do
    let(:candidate_id) { '123456' }
    let(:member_id) { '314' }
    let(:comment) { 'Good, I guess' }
    let(:score) { 'positive' }
    let(:body) do
      {
        member_id: member_id,
        comment: comment,
        score: score
      }
    end

    it 'submits POST request' do
      stub = stub_request(:post, 'https://www.workable.com/spi/v3/accounts/subdomain/candidates/123456/ratings')
        .with(body: body.to_json)

      client.create_rating(candidate_id, member_id, comment, score)
      expect(stub).to have_been_requested.once
    end
  end
end